Scala函数与类二分法

时间:2011-03-28 05:58:42

标签: oop scala functional-programming

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

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

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

3 个答案:

答案 0 :(得分:9)

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

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

答案 1 :(得分:4)

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

class ValueGenerator {
  def value(line: String = "1") = {
    line
  }
}

REPL会议:

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

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

scala> res1.value()
res3: String = 1

请记住,您只能使用方法执行此操作。函数不支持默认参数:

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***

答案 2 :(得分:2)

  

据我所知,至少我的倾向是,在Scala中,规范是传递方法。

我怀疑这是常态(你为什么这么认为?)或者Scala中甚至有这样的规范。

  

但在这种情况下,虽然方法做同样的事情,但它们没有相同的签名,因此不能互相替换(或者它们可以吗?)。换句话说,无论函数的签名如何,发送方方法都可以决定要发送的函数吗?

它们不能互相替代,因为它们具有不同的签名,因此它们具有不同的类型。

您描述的场景听起来非常适合OO操作方式:只需传递ValueGenerator对象,让客户端决定在该对象中调用哪个方法。