我看到一些代码写特征如下:
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
我想知道错误发生的原因以及如何以这种方式使用特征?
答案 0 :(得分:22)
发生错误是因为您已将this
引用(您将其命名为self
)的类型约束为类型Self
。当您说new Self with SelfAware
时,这没关系,因为该对象的类型为Self
,就像您问的那样。但是当您说new X with SelfAware
时,没有证据表明X
在任何方面都是Self
的子类型。
在X with SelfAware
类型的新对象中,self
成员的类型是什么?好吧,它不是Self
类型,而是X
类型。但是您已经定义了特征SelfAware
,因此self
必须是Self
类型,因此您会遇到类型错误。
答案 1 :(得分:21)
我也在这里找到答案:http://markthomas.info/blog/?p=92
订购可以混合到任何类;它不依赖于它所混合的类的任何方法或字段。有时候,一个特性能够使用它所混合的类的字段或方法是有用的,这可以通过为特征指定一个自我类型来完成。可以为类或特征指定自我类型,如下所示:
trait SpellChecker { self =>
...
}
在这个特性的上下文中的自我将参考这个。别名这对嵌套类或特征非常有用,否则很难访问特定的类。语法可以扩展为指定下限,当完成此操作时,trait或类可以使用此下限类的功能,因此它可以扩展或修改其行为。
trait SpellChecker { self: RandomAccessSeq[char] =>
...
}
编译器将检查包含SpellChecker的层次结构中的任何类是否为或扩展RandomAccessSeq [char],因此SpellChecker现在可以使用RandomAccessSeq [char]
的字段或方法答案 2 :(得分:12)
要回答问题的另一半(为什么println(s.self)
会产生错误?),这是因为self
不是SelfAware
的字段。但是,它可用于定义此类字段:
trait SelfAware { self =>
val me = self
}
class X
val x = new X with SelfAware
println(s.me)