Trait的重写方法(Int => Int => Int)

时间:2015-07-04 01:57:35

标签: scala

鉴于以下特点:

scala> trait Foo { 
     |   def f: Int => Int => Int
     | }
defined trait Foo

我创建了一个试图实例化Foo#f的类:

scala> class FooImpl extends Foo {
     |  override def f(x: Int, y: Int) = 100
     | }
<console>:11: error: class FooImpl needs to be abstract, since method f in trait Foo of type => Int => (Int => Int) is not defined
       class FooImpl extends Foo {
             ^

我能用以下方法解决它:

scala> class FooImpl extends Foo {
     |   override def f = x => y => 100
     | }
defined class FooImpl

然后我可以创建一个实例:

scala> new FooImpl().f(10)(20)
res3: Int = 100

但是,我如何创建一个Foo的实现,用[{1}}实现Foo#f,即不用curry?

最后,我试过了:

def f(x: Int, y: Int) = 100

但那也失败了:

scala> trait Bar { def f: (Int, Int) => Int }
defined trait Bar

3 个答案:

答案 0 :(得分:7)

这些类型不兼容。

def f: Int => Int => Int

..是一个无参数方法,返回带有一个参数Int函数,它返回一个带有一个参数Int的函数,返回Int

def f: (Int, Int) => Int

..是一个无参数方法,它返回一个带有Int类型参数的函数,返回Int

def f(x: Int, y: Int): Int

..是一个带有两个Int参数的双参数方法,返回Int

所有这些都是根本不同的。你不能用任何其他方式覆盖它们中的任何一个。如果您想要f(x: Int, y: Int): Int,那么首先应该是Foo中的签名。否则,你必须进行咖喱,eta-expand或其他东西才能使签名匹配。

答案 1 :(得分:0)

如果你想让特性定义非咖喱版本,那么它需要是这样的:

trait Foo {
  def f(x: Int, y: Int): Int
}

此处(x: Int, y: Int)表示f接受Int的两个参数,: Int表示返回值必须为Int

答案 2 :(得分:0)

这是如何创建实现FooImpl特征的Foo。我们也可以在没有currying的情况下访问Foo #f。

trait Foo{
def f1:Int=> Int=> Int
def f2: (Int, Int) => Int
}

class FooImpl extends Foo{

    //actual implementors of f1 and f2 in Foo trait
    def g0=g1
    def g1=g2
    def g2=20
    def add(a:Int, b:Int)=a+b

    override  def f1=g0=>g1=>g2
    override def f2=add 
}

现在我们可以实例化FooImpl类,而不必讨论。

var x = new FooImpl
println(x.f1.apply(1).apply(1))  //results 20
println(x.f2(10,10))             //results 20