Reputation: 2091
I want to mixin a trait so that I can use a method from to return my own trait type. For example,
> 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...
I know that I'm thinking about this in too much an OO fashion by using the asInstanceOf
, and am ignorant in regards to something basic about the way traits work in Scala. How should I change N and its sub-types?
Upvotes: 0
Views: 301
Reputation: 52691
M.name
constructs and returns a foo
. In N.name
you call super.name
. Since super.name
refers to M.name
, super.name
also constructs and returns a foo
. You then take that foo
and call .asInstanceOf[bar]
. But this doesn't make sense since nothing in your code ever constructed a bar
, and, while a bar
is a foo
, a foo
is not necessarily a bar
.
If you really want N.name
to return a bar
, then you need to override M.name
so that you explicitly construct a bar
and return it.
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`
}
}
Now we get:
scala> println(t.name.blah)
name
Upvotes: 2