2015-07-04 2 views
1

Учитывая такую ​​особенность:Перекрытие Метод (Int => Int => Int) из Trait

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, который реализует Foo#f с def f(x: Int, y: Int) = 100, то есть без выделки?

Наконец, я попробовал:

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

Но это тоже не получилось:

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

ответ

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 или что-то еще, чтобы подписи совпадали.

0

Если вы хотите черту, чтобы определить, не выделанной версии, то это должно было бы быть так:

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

(x: Int, y: Int) здесь говорит, что f принимает два параметра Int и : Int говорит, что возвращаемое значение должно быть Int.

0

Вот как можно создать FooImpl, который реализует черту Foo. Мы также можем получить доступ к Foo # f без currying.

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 
Смежные вопросы