OOP では、実装ではなくインターフェイスと対話することをお勧めします。したがって、たとえば、次のように記述します (つまりSeq
:) scala.collection.immutable.Seq
):
// talk to the interface - good OOP practice
doSomething[A](xs: Seq[A]) = ???
次のようなものではありません。
// talk to the implementation - bad OOP practice
doSomething[A](xs: List[A]) = ???
ただし、Haskell などの純粋な関数型プログラミング言語では、サブタイプ ポリモーフィズムはなく、代わりに型クラスによるアドホック ポリモーフィズムを使用します。したがって、たとえば、list データ型と list のモナド インスタンスがあります。そのような概念がないため、インターフェイス/抽象クラスの使用について心配する必要はありません。
Scala などのハイブリッド言語では、型クラス (実際にはパターンを介して、Haskell のようなファーストクラスの市民ではありませんが、余談ですが) とサブタイプのポリモーフィズムの両方があります。scalaz
などではcats
、もちろん、抽象型ではなく、具象型のモナド インスタンスがあります。
最後に質問: Scala のこのハイブリッド性を考慮して、インターフェイスと対話するための OOP 規則を引き続き尊重しますか、それとも、使用する必要があるたびに具象型に変換する必要なく、ファンクターやモナドなどを直接利用するために具象型と対話しますか?彼ら?別の言い方をすれば、OOP の代わりに FP を採用したい場合でも、インターフェースと対話することは Scala でまだ良い習慣ですか? そうでない場合は、使用することを選択し、後でa の方が適切な選択List
であることに気付いたとしたらどうしますか?Vector
PS: 私の例では単純な方法を使用しましたが、同じ理由がユーザー定義型にも当てはまります。例えば:
case class Foo(bars: Seq[Bar], ...)