简体   繁体   English

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

[英]Overriding implicit setter method with a trait in Scala

I'm trying to implement a stackable trait pattern in Scala (similar to http://www.artima.com/scalazine/articles/stackable_trait_pattern.html ). 我正在尝试在Scala中实现可堆栈特征模式(类似于http://www.artima.com/scalazine/articles/stackable_trait_pattern.html )。 Here's my attempt. 这是我的尝试。 I start defining a simple class: 我开始定义一个简单的类:

class Topping(var name:String)

That class declaration should automatically create a getter and a setter method for variable called "name". 该类声明应为名为“ name”的变量自动创建一个getter和setter方法。 So then I create a trait extending this class: 因此,我创建了一个扩展此类的特征:

trait LoggingNameTrait extends Topping {

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

}

If the code above worked, it should override the implicit setter for the "name" field, printing it on the console and then calling the setter of the class which uses the trait. 如果上面的代码有效,则它应覆盖“名称”字段的隐式setter,在控制台上打印它,然后调用使用trait的类的setter。 I get a "super may not be used on variable name". 我得到一个“超级可能不能在变量名上使用”。

Do you know why the Scala compiler doesn't let me override the implicit setter? 您知道为什么Scala编译器不让我覆盖隐式setter吗?

It's an implementation restriction: super only works for def s. 这是一个实现限制: super仅适用于def

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

设置器的名称不是name_ ,而是name_= (请注意等号)。

I believe that though scala in some sense creates the name_= method automatically when you declare the variable, it is not available for overriding and the like unless you declare it explicitly. 我相信,尽管从某种意义上来说,scala在声明变量时会自动创建name_=方法,但除非明确声明,否则它不可用于覆盖等。 The following, however, should work: 但是,以下方法应该起作用:

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   }

}

This should be functionally equivalent to what you were trying initially, 这在功能上应与您最初尝试的功能相同,

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

Will print out "Name" and set the internal _name value, such that val s = t.name will assign "Name" to s , as you would expect. 将打印出“名”,并设置内部_name值,使得val s = t.name将指派“名称”,以s ,如你所愿。 The only difference is the more explicit definition of the setter and getter functions. 唯一的区别是对setter和getter函数的更明确的定义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM