4

次のコードはエラーを出します:

package test

trait Base {
  def method:String
}

trait Trait extends Base {
  def method()(implicit i:String):String = { "2" }
}

object Object extends Trait {

}

エラーは「タイプ=>文字列のクラスBaseのメソッドメソッドが定義されていないため、オブジェクトの作成が不可能です」です。

上記のエラーは次のコードで修正されています

package test

trait Base {
  def method:String
}

trait Trait extends Base {
  def method:String = method()("String") // Over loading
  def method()(implicit i:String):String = { "2" }
}

object Object extends Trait {

}

ここで、Scalaクラスの代わりに、Javaインターフェイスを次のように定義すると次のようになります。

// Java Code
package test;

public interface JBase {
  String method();
}

// Scala Code
package test

trait Trait extends JBase {
  def method:String = method()("10")
  def method()(implicit i:String):String = { "2" }
}

object Object extends Trait {

}

「オーバーロードされた定義へのあいまいな参照、タイプ()(implicit i:String)Stringの特性特性のメソッドメソッドとタイプ()Stringの特性特性のメソッドメソッドの両方が引数types()に一致します」というエラーが表示されます。

コンパイラの動作が異なるこれら両方のシナリオの違いは何ですか?この問題を解決するにはどうすればよいですか?

4

1 に答える 1

7

何が起こっているのかを明確に示していると思う例を次に示します。

object Test extends App {
    class A { def f(): String = "x" }
    class B extends A { override def f: String = "y" }
    class C { def f: String = "z" }

    println { (new A).f() } // OK
    println { (new B).f() } // OK
    println { (new C).f() } // FAILS
}
  • A: カッコあり、カッコあり、なんでもいい。
  • B:括弧はありませんが、スーパータイプには括弧があり、それでも問題ありません。これはあなたのケースに対応しています。
  • C: 括弧なし、括弧付き呼び出し、ダメ。

基本的に、Java メソッドは常に「括弧付き」と見なされるため、Traitのスーパータイプには括弧が含まれているため、括弧を使用しても、method()("string")意味するメソッドを明確にするには不十分です。


編集:正直なところ、メソッドの名前を変更したほうがよいと思います。あいまいさがない場合でも、動作は非常に驚くべきものになる可能性があります。

trait Trait {
    def method: String = method()("x")
    def method()(implicit i: String): String = i
}

val t = new Trait { }
implicit val s = "y"

println { t.method }
> "x"

println { t.method() }
> "y"

さらに、名前が同じであるという事実は、ポリモーフィズムの観点からは何のメリットもありません。非暗黙的なメソッドのみがオーバーライドされますBase.method。名前を同じにするのは美的決定にすぎません。

于 2013-01-13T19:17:21.043 に答える