在 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)中,您没有子类型多态性,而是通过类型类使用临时多态性。因此,例如,您有列表数据类型和列表的一元实例。您无需担心使用接口/抽象类,因为您没有这样的概念。
在 Scala 等混合语言中,您同时拥有类型类(实际上是通过模式,而不是像 Haskell 中的一等公民,但我离题了)和子类型多态性。在scalaz
,cats
等等中,你有具体类型的单子实例,当然不是抽象的。
最后的问题是:鉴于 Scala 的这种混合性,您是否仍然尊重 OOP 规则来与接口对话,或者只是与具体类型对话以直接利用函子、单子等,而无需在需要时转换为具体类型。他们?换句话说,即使您想采用 FP 而不是 OOP,在 Scala 中与接口对话是否仍然是一种好习惯?如果不是,如果您选择使用List
,并且后来您意识到 aVector
会是更好的选择,该怎么办?
PS:在我的示例中,我使用了一种简单的方法,但同样的推理也适用于用户定义的类型。例如:
case class Foo(bars: Seq[Bar], ...)