我想混合一个特征,以便我可以使用一个方法来返回我自己的特征类型。例如,
> trait M {
trait foo {def blah = "foo" }
def name:foo = { new foo { override def blah = "name"}}}
> trait N extends M {
trait bar extends foo {}
override def name:bar = super.name.asInstanceOf[bar]}
> object t extends N { val baz = name }
> t.name
java.lang.ClassCastException: M$$anon$1 cannot be cast to N$bar
at N$class.name(<console>:7)
at t$.name(<console>:8)
at t$.<init>(<console>:8)
at t$.<clinit>(<console>)
at .<init>(<console>:10)
at .<clinit>(<console>)
at RequestResult$.<init>(<console>:9)
at RequestResult$.<clinit>(<console>)
at RequestResult$scala_repl_result(<console>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:616)
at scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1$$anonfun$apply$17.apply(Interpreter.scala:988)
at scala.tools.nsc.Interpreter$Request$$anonfun$l...
我知道我正在使用asInstanceOf
以太多OO的方式考虑这个问题,并且对于Scala中特征的工作方式基本无知。我该如何更改N及其子类型?
答案 0 :(得分:2)
M.name
构造并返回foo
。在N.name
中,您拨打super.name
。由于super.name
引用M.name
,super.name
也构造并返回foo
。然后,您取出foo
并致电.asInstanceOf[bar]
。但是这没有意义,因为代码中的任何内容都没有构建bar
,而bar
是foo
,foo
不一定是{{} 1}}。
如果您真的希望bar
返回N.name
,则需要覆盖bar
,以便明确构建M.name
并将其返回。
bar
现在我们得到:
trait N extends M {
trait bar extends foo {}
override def name: bar ={
val f: foo = super.name // not what we want; it's not a `bar`
new bar { override def blah = f.blah } // this is actually a `bar`
}
}