Reputation: 181
Why doesn't this work:
scala> trait A
defined trait A
scala> class Z {
| this: A =>
| }
defined class Z
scala> class Y {
| this: A =>
| val z = new Z()
| }
<console>:11: error: class Z cannot be instantiated because it does not conform to its self-type Z with A
val z = new Z()
I want the A that is mixed into Y to be again mixed into the instance of Z in Y. How can I do that?
EDIT (was trying to be too brief in the above example. Here's my actual problem):
scala> import scala.slick.driver.ExtendedProfile
import scala.slick.driver.ExtendedProfile
scala> class Z {
| this: ExtendedProfile =>
| }
defined class Z
scala> class Y {
| this: ExtendedProfile =>
| val z = new Z() with ExtendedProfile
| }
<console>:21: error: illegal inheritance;
self-type Z with scala.slick.driver.ExtendedProfile does not conform to scala.slick.driver.ExtendedProfile's selftype scala.slick.driver.ExtendedDriver
val z = new Z() with ExtendedProfile
^
I guess I understand why that doesn't compile, but shouldn't this be implicit (not actual scala keyword 'implicit', just generally implicit ;) )? If an ExtendedProfile always must have an ExtendedDriver, why is new Z() complaining that it needs an ExtendedDriver?
FYI: http://slick.typesafe.com/doc/1.0.0-RC1/api/#scala.slick.driver.ExtendedProfile
Upvotes: 0
Views: 306
Reputation: 21112
The compile error says that you need to provide an A
mix-in to instantiate a Z
object. As om-non-nom suggests, your code compiles with a small change,
trait A
class Z { this: A =>
}
class Y { this: A =>
val z = new Z with A
}
Here's an alternative that uses inheritance instead of a self-type, and may be closer to your intentions:
trait Y extends A {
val z = new Z with Y
}
EDIT
To answer your updated question, the self-type is a constraint on the type construction. Self-types are different from inheritance in that they don't extend the type's external interface.
From the Scaladoc you linked, it looks like this is the situation:
trait ExtendedDriver extends ExtendedProfile
trait ExtendedProfile { self: ExtendedDriver => }
class Z { this: ExtendedProfile => }
class Y {
this: ExtendedProfile =>
val z = new Z() with ExtendedProfile
}
The problem is that ExtendedProfile
does not inherit from ExtendedDriver
, so it can't stand alone; it needs to be provided an explicit ExtendedDriver
. You can do that with
new Z() with ExtendedProfile with ExtendedDriver
That's actually redundant, since ExtendedProfile
is already mixed in. You simply need,
new Z() with ExtendedDriver
Upvotes: 1