scala - 使用参数作为期望类型的子实现trait方法

时间:2012-08-25 16:40:03

标签: scala methods parameters match extends

我是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”的东西,但我似乎无法找到这方面的文档。

3 个答案:

答案 0 :(得分:6)

问题是Bar trait的someMethod声明指定任何类型的Foo都可以作为参数传递。您可以将此视为“合同”。合同规定,Bar的任何实施都会有someMethod方法接受任何类型的Foo

您的BarImpl课程是Bar的实施,并且实施someMethod。不幸的是,它仅someMethod 的实施接受FooImplFoo种对象:任何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.someMethodBarImpl.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