使用Scala中的特征覆盖隐式setter方法

时间:2011-11-26 20:58:58

标签: java scala inheritance traits

我正在尝试在Scala中实现可堆叠的特征模式(类似于http://www.artima.com/scalazine/articles/stackable_trait_pattern.html)。这是我的尝试。我开始定义一个简单的类:

class Topping(var name:String)

该类声明应自动为名为“name”的变量创建getter和setter方法。那么我创建了一个扩展这个类的特性:

trait LoggingNameTrait extends Topping {

  override def name_=(aName:String) {
    print(aName)
    super.name_=(aName) // this line doesn't compile
  }

}

如果上面的代码有效,它应该覆盖“name”字段的隐式setter,在控制台上打印它,然后调用使用该trait的类的setter。我得到一个“超级可能不会用于变量名称”。

你知道为什么Scala编译器不允许我覆盖隐式setter吗?

3 个答案:

答案 0 :(得分:7)

这是一项实施限制:super仅适用于def s。

https://issues.scala-lang.org/browse/SI-1938

答案 1 :(得分:2)

setter不会被称为name_,它被称为name_=(注意等号)。

答案 2 :(得分:1)

我相信虽然scala在某种意义上会在您声明变量时自动创建name_=方法,但除非您明确声明,否则它不能用于覆盖等。但是,以下内容应该有效:

class Topping(var _name:String) {
    def name : String = _name
    def name_= (s : String) { _name = s }
}

trait LoggingNameTrait extends Topping {

  abstract override def name_=(aName:String) {
    print(aName)
    super.name_=(aName) // this line doesn't compile   }

}

这应该在功能上等同于您最初尝试的内容,

val t = new Topping with LoggingNameTrait
t.name = "Name"

将打印出来"姓名"并设置内部_name值,以便val s = t.name分配"名称"如你所料,到s。唯一的区别是setter和getter函数的更明确的定义。