scala嵌套自我类型

时间:2013-01-11 17:01:28

标签: scala self-type

为什么这不起作用:

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()

我希望混合到Y中的A再次混合到Y中的Z实例中。我该怎么做?

编辑(在上面的例子中试图过于简短。这是我的实际问题):

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
                        ^

我想我明白为什么不编译,但不应该是隐式的(不是实际的scala关键字'隐式',只是一般隐含的;))?如果ExtendedProfile总是必须有一个ExtendedDriver,为什么新的Z()抱怨它需要一个ExtendedDriver?

仅供参考:http://slick.typesafe.com/doc/1.0.0-RC1/api/#scala.slick.driver.ExtendedProfile

1 个答案:

答案 0 :(得分:1)

编译错误表明您需要提供A混合来实例化Z对象。正如om-non-nom所示,你的代码只需要很小的改动,

trait A

class Z { this: A =>
}

class Y { this: A =>
  val z = new Z with A
}

这是使用继承而不是自我类型的替代方案,可能更接近您的意图:

trait Y extends A {
  val z = new Z with Y
}

修改

要回答您更新的问题,自我类型是类型构造上的约束。自我类型与继承不同,因为它们不扩展类型的外部接口。

从您链接的Scaladoc,看起来就是这种情况:

trait ExtendedDriver extends ExtendedProfile
trait ExtendedProfile { self: ExtendedDriver => }

class Z { this: ExtendedProfile => }

class Y {
  this: ExtendedProfile =>
  val z = new Z() with ExtendedProfile
}

问题是ExtendedProfile不会继承ExtendedDriver,所以它不能孤立无援;需要提供一个明确的ExtendedDriver。你可以用

做到这一点
new Z() with ExtendedProfile with ExtendedDriver

这实际上是多余的,因为ExtendedProfile已经混入。你只需要,

new Z() with ExtendedDriver