2011-11-26 46 views
3

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

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 
    } 

} 

如果上面的代码工作,它应该覆盖隐含二传手的“姓名”字段中,打印在控制台上,然后调用类的二传手这使用特质。我得到一个“超级可能不能用于变量名称”。

你知道为什么Scala编译器不会让我重写隐式setter吗?

+0

'super.name _ =(aName)//这行不compile'怎么样一个简单的'super.name = aName'?为什么name_抽象的方式? – aishwarya

+0

这不起作用。是的,我应该删除那里的抽象修饰符。谢谢! – ivanfoofoo

回答

2

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

+0

我只是想: '抽象重写高清名_ =(aName:字符串){ 打印(aName) super.name _ =(aName) }' ,它仍然没有工作... :( – ivanfoofoo

+0

虽然这个答案事实上是正确的,它不适用于问题询问。非虚拟队列的答案是正确的。 – Lex

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函数的更明确的定义。

+2

是的,我已经尝试过了,它工作得很好,但我不想声明getter和setter方法,我想重写隐式的!有没有理由不在Scala中工作? – ivanfoofoo

6

这是一个实施限制:super只适用于def s。

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

+0

有趣。但我实际上正在覆盖一个setter(我知道它是一个var的setter,但隐式setter是一个def,对吗?),所以我认为它应该工作。该问题说“特征应该能够在字段上调用超级”,但是我将调用者从调用者这个特点,也被认为是一个实地访问,对吗? – ivanfoofoo

+1

在该错误的评论中添加您的用例。即使它是从不同的角度来看,你也遇到了同样的限制。 – retronym