我看到一些代码编写特征如下:
trait SelfAware { self: Self =>
....
}
class Self
val s = new Self with SelfAware // this is ok
println(s.self) // error happened
class X
new X with SelfAware // error happened here
我想知道为什么会发生错误以及如何以这种方式使用特征?
我看到一些代码编写特征如下:
trait SelfAware { self: Self =>
....
}
class Self
val s = new Self with SelfAware // this is ok
println(s.self) // error happened
class X
new X with SelfAware // error happened here
我想知道为什么会发生错误以及如何以这种方式使用特征?
发生错误是因为您已将this
引用的类型(您已命名self
)限制为 type Self
。当您说 时new Self with SelfAware
,这没关系,因为该对象的类型Self
与您询问的一样。但是当你说的时候new X with SelfAware
,没有任何证据表明它X
是Self
.
在您的新类型对象中X with SelfAware
,其self
成员的类型是什么?好吧,它不是 type Self
,而是 type X
。但是您已经定义了特征SelfAware
,因此它self
必须是 type Self
,所以您会收到类型错误。
我也在这里找到了答案:http: //markthomas.info/blog/ ?p=92
Ordered 可以混入任何类;它不依赖于它所混入的类的任何方法或字段。有时,一个 trait 能够使用它所混入的类的字段或方法很有用,这可以通过为 trait 指定一个自身类型来完成。可以为类或特征指定自我类型,如下所示:
trait SpellChecker { self =>
...
}
在 this trait 的上下文中的 self 将引用 this。别名 this 对于嵌套类或特征很有用,否则很难访问特定的 this。可以扩展语法以指定 this 的下限,完成此操作后,特征或类可以使用此下限类的功能,因此它可以扩展或修改其行为。
trait SpellChecker { self: RandomAccessSeq[char] =>
...
}
编译器将检查包括 SpellChecker 在内的层次结构中的任何类是否是或扩展了 RandomAccessSeq[char],因此 SpellChecker 现在可以使用 RandomAccessSeq[char] 的字段或方法
要回答您问题的另一半(为什么会println(s.self)
产生错误?),那是因为self
不是SelfAware
. 但是,它可用于定义此类字段:
trait SelfAware { self =>
val me = self
}
class X
val x = new X with SelfAware
println(s.me)