ここでは、スーパークラスのセッター/ゲッターを直接参照する必要があります。通常、次のように書く必要があります。
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.name.apply()
(文字列は暗黙的な変換を通じてこのメソッドを取得できる)と見なすため、ゲッターはコンパイルしません。
いくつかのオプションがあります。
- 継承よりも構成を優先します(クラシック)。
- 変数名を変更してプライベートにし、スーパークラスにアクセサーを書き込みます(以下を参照)。
- リフレクション/手動名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
}
}
}