如何使用scala trait与`self`引用?

时间:2012-04-24 02:56:12

标签: scala

我看到一些代码写特征如下:

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

我想知道错误发生的原因以及如何以这种方式使用特征?

3 个答案:

答案 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)