我是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) {} }
为什么FooImpl与Foo不匹配,因为Foo是一个特质?我猜我需要改变Bar中someMethod的签名,说我期待扩展Foo或“with Foo”的东西,但我似乎无法找到这方面的文档。
答案 0 :(得分:6)
问题是Bar
trait的someMethod
声明指定任何类型的Foo
都可以作为参数传递。您可以将此视为“合同”。合同规定,Bar
的任何实施都会有someMethod
方法接受任何类型的Foo
。
您的BarImpl
课程是Bar
的实施,并且实施someMethod
。不幸的是,它仅someMethod
的实施接受FooImpl
种Foo
种对象:任何种Foo
。由于它不允许您传入非Foo
个对象的FooImpl
个对象,因此它违反了特征定义指定的合同。实施不能比合同规定的限制更多。
举个例子:
class FooImplB extends Foo
val bar: Bar = new BarImpl
val foo: Foo = new FooImplB
bar.someMethod(foo)
我们在此声明名为Bar
的{{1}}和bar
Foo
。根据{{1}}的定义,我应该能够将foo
传递给Foo
。除了foo
只接受bar.someMethod
种BarImpl.someMethod
s而不是FooImpl
s!所以我们遇到了问题。
答案 1 :(得分: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) {}
}
答案 2 :(得分: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