3

私は Scala に非常に慣れていないので、これが本当に簡単な質問である場合は許してください。どうすればこれを機能させることができますか?

scala> trait Foo
defined trait Foo

scala> class FooImpl extends Foo
defined class FooImpl

scala> trait Bar { def someMethod(foo: Foo) }
defined trait Bar

scala> class BarImpl extends Bar { def someMethod(foo: FooImpl) {} }
<console>:10: error: class BarImpl needs to be abstract, since method someMethod in trait Bar of type (foo: Foo)Unit is not defined
(Note that Foo does not match FooImpl)
       class BarImpl extends Bar { def someMethod(foo: FooImpl) {} }

Foo は特性であるため、FooImpl が Foo と一致しないのはなぜですか? Bar の someMethod のシグネチャを変更して、Foo または "with Foo" を拡張するものを期待していると言う必要があると思いますが、これに関するドキュメントが見つからないようです。

4

3 に答える 3

6

問題は、BarトレイトのsomeMethod宣言で、あらゆる種類の をFoo引数として渡すことができると指定されていることです。これを「契約」と考えることができます。契約では、 の実装には、あらゆる種類の を受け入れるBarメソッドがあると書かれています。someMethodFoo

あなたのBarImplクラスはの実装でBarあり、実装がありsomeMethodます。残念ながら、 の実装はオブジェクト種類someMethod のみを受け入れます。オブジェクトではないオブジェクトを渡すことができないため、特性定義で指定された契約に違反しています。実装は、契約で指定されているよりも厳しくすることはできません。FooImplFooFooFooFooImpl

例として:

class FooImplB extends Foo
val bar: Bar = new BarImpl
val foo: Foo = new FooImplB
bar.someMethod(foo)

ここで、BarcalledbarFoocalledを宣言しfooます。の定義によれば、 I は に渡すことFooができるはずです。ただし、の種類のみを受け入れ、 は受け入れません! 問題があります。foobar.someMethodBarImpl.someMethodFooImplFooFooImplB

于 2012-08-25T16:45:10.593 に答える
4

dhg は、なぜこれがうまくいかないのか、なぜあなたはおそらく本当にそれを望んでいないのかを説明しました.

ただし、それでも必要な場合は、次のようにすることができます。

trait Foo

class FooImpl extends Foo

trait Bar[F <: Foo] { def someMethod(foo: F) }

class BarImpl extends Bar[FooImpl] {
    def someMethod(foo: FooImpl) {}
}
于 2012-08-25T21:56:21.347 に答える
0

Jens Schauder の答えは機能しますが、特性シグネチャで型を定義する必要があります。代わりに、メソッド レベルで同じことを行うことができます。

scala> trait Foo
defined trait Foo

scala> class FooImple extends Foo
defined class FooImple

scala> trait Bar { def methodA[T <: Foo](foo: T) }
defined trait Bar

scala> class BarImpl extends Bar { def methodA[FooImpl](foo: FooImpl){} }
defined class BarImpl
于 2012-08-26T01:31:03.460 に答える