2012-04-30 3 views
6

に私はこのオーバーライドカリー化関数スカラ

// short syntax 
def foo(bar: Bar)(baz: Baz): Quux 

この

// long syntax 
def foo(bar: Bar): (Baz) => Quux 

のためのシンタックスシュガーだった。しかし、それは相続に来るとき、私は2を混ぜるように見えることはできませんという印象の下にありました。ツリー全体は、短い構文または長い構文のいずれかで定義する必要があります。どちらも決してありません。例えば

case class Context 
case class Work 

trait ContextualWorker { 
    def workWithContext(ctxt: Context)(work: Work): Traversable[Work] 
} 

class ShortConcreteWorker extends ContextualWorker { 
    override def workWithContext(ctxt: Context)(work: Work) = Nil 
} 

class LongConcreteWorker extends ContextualWorker { 
    // error on next line: method workWithContext overrides nothing <------------- 
override def workWithContext(ctxt: Context): (Work) => Traversable[Work] = { 
    val setupCode = 1 
    { work => Nil } 
    } 
} 

私は長い構文を使用する形質を変更する場合は、ShortConcreteWorkerはコンパイルされません。

これらが継承/交換することはできません理由はありますか?あなたはどうしたのですか?

は今のところ最も柔軟なアプローチは、おそらくそうのようShortConcreteWorkerに実装クラスに委譲し、長い構文のツリーを定義するように表示されます。

case class Context 
case class Work 

trait ContextualWorker { 
    def workWithContext(ctxt: Context): (Work) => Traversable[Work] 
} 

class ShortConcreteWorker extends ContextualWorker { 
    override def workWithContext(ctxt: Context) = workWithContextImpl(ctxt)_ 
    private def workWithContextImpl(ctxt: Context)(work: Work) = Nil 
} 

class LongConcreteWorker extends ContextualWorker { 
    override def workWithContext(ctxt: Context): (Work) => Traversable[Work] = { 
    val setupCode = 1 
    { work => Nil } 
    } 
} 
+0

私はあなたが[このページはScalaのサイト](http://www.scala-lang.org/node/135)に基づいていると思います。残念ながら、それはかなり正確ではありません.Scala仕様の3.3.1節を参照してください。 – rxg

答えて

5

非常に単純に説明する2つの方法が異なるシグネチャを持っています。最初は別々の引数リストで与えられた二つの引数を、必要とし、Intを返す関数である

scala> def foo1(a: Int)(b: Int): Int = a + b 
foo1: (a: Int)(b: Int)Int 

scala> def foo2(a: Int): (Int => Int) = (b: Int) => a + b 
foo2: (a: Int)Int => Int 

:REPLはこれを確認しました。第二は、引数を取り、IntIntから機能を返す関数です。これらの2つの概念は概念的には似ていますが、実際は異なる構文であり、Scalaはそれらをそのまま扱います。

これは、複数の引数リストを持つ関数に限定されるものではありません。ここでも同じように動作します:

scala> def foo3(a: Int): Int = a + 1 
foo3: (a: Int)Int 

scala> def foo4: (Int => Int) = (a: Int) => a + 1 
foo4: Int => Int 

使用法にもさまざまな影響があります。 foo2では、1つの引数しか受け付けないので、1つの引数で呼び出すことができます。しかし、foo1ので、我々は単に1でそれを呼び出すことはできません、2つの引数が必要です。あなたはは、しかし、呼び出し可能な関数に変換する_構文を使用することができます。

あなたの質問に直接答える:彼らは交換できない理由は同じではないからです。彼らが同じであれば、同じ方法で呼ぶことができます。拡張時にシグネチャを変更できる場合、Scalaはどの呼び出し構文を許可するのかこれを "回避"する方法は、単純にシグネチャを一貫させることです。

+0

それは我々が持っている場合、例えば、 'DEF gがあることを追加すると便利かもしれません(F:のInt => INT)'、我々はグラム 'としてそれを呼び出すことができます(foo1は(3))'や 'グラム(foo2は(3) ) '。したがって、特定の状況下では、2つのスタイルは区別できません。 – rxg

関連する問題