物体功能阻抗不匹配

时间:2016-05-09 12:55:32

标签: scala oop functional-programming scalaz scala-cats

在OOP中,最好 talk 接口而不是实现。所以,例如,你写这样的东西(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)中,您不具有子类型多态性,而是通过类型类使用ad hoc多态。因此,例如,您具有列表数据类型和列表的monadic实例。您不必担心使用界面/抽象类,因为您没有这样的概念。

在混合语言中,例如Scala,你有两种类型类(通过模式,实际上,而不是像Haskell中的一等公民,但我离题)和子类型多态。在scalazcats等等,你有具体类型的monadic实例,当然不是抽象实例。

最后一个问题:鉴于Scala的 hybridism ,你仍然尊重OOP规则来与接口交谈,或者只是与具体类型交谈以直接利用函子,monad等,而不必只要你需要使用它们就转换成具体类型?换句话说,即使你想拥抱FP而不是OOP,Scala仍然是很好的实践与界面交谈?如果没有,如果您选择使用List会怎么样?之后,您意识到Vector会是更好的选择?

P.S。:在我的例子中,我使用了一种简单的方法,但同样的推理也适用于用户定义的类型。例如:

case class Foo(bars: Seq[Bar], ...)

1 个答案:

答案 0 :(得分:1)

我在这里攻击的是你的“具体与界面”概念。以这种方式看待它:每种类型都有一个接口,一般意义上的术语“接口”。 “具体”类型只是一种限制性案例。

让我们从这个角度看看Haskell列表。列表的界面是什么?列表是代数数据类型,所有这些数据类型都具有相同的通用形式的接口和契约:

  1. 您可以根据其实体和参数类型使用其构造函数构造类型的实例;
  2. 您可以根据其实体和参数类型与其构造函数进行匹配来观察类型的实例;
  3. 构造和观察是相反的 - 当你对一个值进行模式匹配时,你得到的就是放入它的内容。
  4. 如果你用这些术语来看待它,我认为以下规则在这两种范例中都能很好地运作:

    • 根据您的要求选择接口和合同与完全匹配的类型。
      • 如果他们的合同比你的要求弱,那么他们就不会维持你需要的不变量;
      • 如果他们的合同强于您的要求,您可能会无意中将自己与“额外”细节结合起来,并限制您稍后更改程序的能力。

    所以你不再问一个类型是“具体”还是“抽象” - 只是它是否符合你的要求。