Question

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

Was it helpful?

Solution

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top