为什么这不起作用:
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
答案 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