2012-12-28 33 views
9

比方说,我们有一个类有“名”属性:简单的斯卡拉的getter/setter覆盖

class SuperFoo(var name: String) 

如果我想重写这一点,例如周围添加调用一些锁定:

class SubFoo(n: String) extends SuperFoo(n) { 
    val lock = new ReentrantLock 
    override def name(): String = 
    { 
     lock.lock 
     try { 
     super.name 
     } finally { 
     lock.unlock 
     } 
    } 
    override def name_=(arg: String): Unit = { 
    lock.lock 
    try { 
     super.name = arg 
    } finally { 
     lock.unlock 
    } 
    } 
} 
上述

将产生编译错误:

super may be not be used on variable name 

任何想法如何正确地实现这一点? (即,重写getter & setter以在它们周围添加锁定)。谢谢!

+0

编译器似乎认为我重写了一个变量:如果我从getter中删除了super.name语句,我收到了以下错误消息:“重写类型为String的类SuperFoo中的变量名称;方法名称不能覆盖变量” – Nikolaos

回答

6

在这里你需要直接引用超级类的setter/getter。通常情况下,你应该写这样的:

class SubFoo(n: String) extends SuperFoo(n) { 
    val lock = new ReentrantLock 
    override def name(): String = 
    { 
     lock.lock 
     try { 
     super.name() 
     } finally { 
     lock.unlock 
     } 
    } 
    override def name_=(arg: String): Unit = { 
    lock.lock 
    try { 
     super.name_=(arg) 
    } finally { 
     lock.unlock 
    } 
    } 
} 

但是,如果setter方法编译没有任何问题,吸气不会因为编译器将会把它看作super.name.apply()(字符串可以打通的隐式转换此方法)。

我看到几个选项:在继承

  1. 青睐组成(经典)。
  2. 更改变量名称,使其变为私人并在超类中编写访问器(请参见下文)。
  3. 度假村反思/手动名称umangling伏都教。

我会去的选项#1,但这里是选项#2代码:

class SuperFoo(private var nameVar: String) { 
    def name: String = nameVar 
    def name_=(arg: String): Unit = nameVar = arg 
} 

class SubFoo(n: String) extends SuperFoo(n) { 
    val lock = new ReentrantLock 
    override def name(): String = 
    { 
     lock.lock 
     try { 
    super.name 
     } finally { 
     lock.unlock 
     } 
    } 
    override def name_=(arg: String): Unit = { 
    lock.lock 
    try { 
     super.name = arg 
    } finally { 
     lock.unlock 
    } 
    } 
} 

编辑:这是一个可行的实施选项1:

trait Foo { 
    def name: String 
    def name_=(arg: String): Unit 
} 

class SimpleFoo(var name: String) extends Foo 

class LockedFoo(foo: Foo) extends Foo { 
    val lock = new ReentrantLock 
    def name(): String = 
    { 
     lock.lock 
     try { 
     foo.name 
     } finally { 
     lock.unlock 
     } 
    } 
    def name_=(arg: String): Unit = { 
    lock.lock 
    try { 
     foo.name = arg 
    } finally { 
     lock.unlock 
    } 
    } 
} 
+0

谢谢,我试图避免选项2,并以某种方式使用您的选项1(由于反射,选项3不存在)。但是,即使属性不是字符串,选项1也不会编译,请尝试使用Int,您会看到我的意思。 Scalac认为你想重写'name'字段出于某种原因...任何想法如何获得选项1使用例如一个Int? – Nikolaos

+0

我添加了选项1解决方案。遵循GoF准则,装饰器设计模式允许向现有实现添加行为。 – paradigmatic