Scala函数与类二分法

del*_*met 6 oop functional-programming scala

我刚开始学习Scala.我对OO设计很满意,而功能编程却不那么简单; 虽然,我编程的时间足够长,FP对我来说也不是完全不自然.从我斯卡拉冒险的第一天开始,我就已经说过了,对OO和FP之间正在发生的明显辩证法感到不安.显然,人们可以一路走来.我的第一个倾向是将类看作是一种包含我想要传递的功能的包,这平衡了功能方面的尺度.我觉得必须有一种更好的方法来平衡这种行为.在这种情况下,我也不确定如何处理某些熟悉的情况.例如,如果我有以下(人工)类:

class ValueGenerator {
    def value() = {
        "1"
    }
    def value(line: String) = {
        line
    }
}
Run Code Online (Sandbox Code Playgroud)

在OO编程中,我会value在需要时用适当的签名调用,以获得我需要的结果.这些方法具有相同的签名,因为它们在逻辑上对应于类似的操作.在OO中,我会传递对象引用,接收ValueGenerator对象的方法将value根据情况调用右边的对象.据我所知,至少我的倾向是,在Scala中,规范是传递方法.但在这种情况下,虽然方法做同样的事情,但它们没有相同的签名,因此不能互相替换(或者它们可以吗?).换句话说,无论函数的签名如何,发送方方法都能决定要发送的函数吗?这似乎不太可能,因为接收器不知道如何调用它.在这种情况下,正确的行动是什么.或者一个人的直觉本能?在谈到OO和FB时,你会遵循一条经验法则吗?

作为旁注,很有意思的是,我的一位正在学习Scala的朋友在这个问题上有与我一样的确切想法(或缺乏).

Apo*_*isp 9

它们没有相同的签名,通常您希望不具有相同签名的方法具有不同的名称.重载只会给您带来很少的成本,并且会花费很多(即类型推断和隐式解析).

也就是说,它们不能互相替代,因为它们没有相同的类型.如果要将这些方法转换为函数,则可以使用类型Function0[String],而另一个则具有类型Function1[String, String].


dby*_*rne 4

在您提供的代码中,没有理由需要有两个单独的方法签名:

class ValueGenerator {
  def value(line: String = "1") = {
    line
  }
}
Run Code Online (Sandbox Code Playgroud)

REPL 会话:

scala> new ValueGenerator()
res1: ValueGenerator = ValueGenerator@fa88fb

scala> res1.value("Foo")
res2: String = Foo

scala> res1.value()
res3: String = 1
Run Code Online (Sandbox Code Playgroud)

请记住,您只能使用方法来做到这一点。函数不支持默认参数:

scala> val f = res1.value(_)
f: (String) => String = <function1>

scala> f("Bar")
res5: String = Bar

scala> f()
***Oops***

scala> val f = (line: String) => line      
f: (String) => String = <function1>

scala> val f = (line: String = "1") => line
***Oops***
Run Code Online (Sandbox Code Playgroud)