Here you need to refer directly to the super class setter/getter. Normally you should write something like:
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 } } }
However, if the setter will compile without any problem, the getter won't because the compiler will view it as super.name.apply() (Strings can get this method through implicit conversions).
I see several options:
- Favor composition over inheritance (a classic).
- Change the variable name, make it private and write accessor in the super-class (see below).
- Resort to reflection/manual name umangling voodoo.
I'll go for option #1, but here is code for option #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 } } }
EDIT: Here is a workable implementation of option #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 } } }