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) {} }

为什么 FooImpl 不匹配 Foo 因为 Foo 是一个特征?我猜我需要在 Bar 中更改 someMethod 的签名,以说明我期待扩展 Foo 或“with Foo”的东西,但我似乎找不到这方面的文档。

4

3 回答 3

6

问题是Bartrait 的someMethod声明指定任何类型的Foo都可以作为参数传递。你可以把它想象成它的“契约”。合同说,任何实现Bar都会有一个方法someMethod可以接受任何类型的Foo.

你的BarImpl类是一个实现Bar并且有一个someMethod实现。不幸的是,它的实现someMethod 接受FooImpl各种Foo对象:不接受任何类型的Foo. 由于它不允许您传入Foo不是FooImpl对象的对象,因此它违反了 trait 定义指定的契约。实施不能比合同规定的更严格。

举个例子:

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

这里我们声明了一个Bar被调用的bar和一个Foo被调用的foo。根据Foo我的定义应该可以foo传入bar.someMethod. 除了BarImpl.someMethod只接受FooImplsFoo而不接受FooImplBs!所以我们有一个问题。

于 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 回答