【问题标题】:Overriding implicit setter method with a trait in Scala在 Scala 中使用 trait 覆盖隐式 setter 方法
【发布时间】:2011-11-26 20:58:58
【问题描述】:

我正在尝试在 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”字段的隐式设置器,在控制台上打印它,然后调用使用该特征的类的设置器。我得到一个“超级不能用于变量名”。

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

【问题讨论】:

  • super.name_=(aName) // this line doesn't compile 一个简单的super.name=aName 怎么样?顺便说一下为什么name_是抽象的?
  • 那行不通。是的,我应该删除那里的抽象修饰符。谢谢!

标签: java scala inheritance traits


【解决方案1】:

这是一个实现限制:super 仅适用于 defs。

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

【讨论】:

  • 有趣。但我实际上是在尝试覆盖一个 setter(我知道它是一个 var 的 setter,但隐式 setter 是一个 def,对吧?),所以我认为它应该可以工作。那个问题说“特征应该能够在字段上调用超级”,但我从特征调用设置器,这也被认为是字段访问,对吗?
  • 在该错误的 cmets 中添加您的用例。即使从不同的角度来看,您也遇到了同样的限制。
【解决方案2】:

setter 不叫name_,它叫name_=(注意等号)。

【讨论】:

  • 我刚试过:abstract override def name_=(aName:String) { print(aName) super.name_=(aName) } 还是不行... :(
  • 虽然这个答案实际上是正确的,但它不适用于提出的问题。 nonVirtualThunk 的答案是正确的。
【解决方案3】:

我相信虽然 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 函数的定义更明确。

【讨论】:

  • 是的,我已经尝试过了,效果很好。但我不想声明 getter 和 setter 方法,我想覆盖隐式方法!这在 Scala 中不起作用有什么原因吗?
猜你喜欢
  • 2012-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多