9

'name'プロパティを持つクラスがあるとしましょう:

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 

これを正しく実装する方法はありますか?(つまり、ゲッターとセッターをオーバーライドして、それらの周りにロックを追加します)。ありがとう!

4

1 に答える 1

6

ここでは、スーパークラスのセッター/ゲッターを直接参照する必要があります。通常、次のように書く必要があります。

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()(文字列は暗黙的な変換を通じてこのメソッドを取得できる)と見なすため、ゲッターはコンパイルしません。

いくつかのオプションがあります。

  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
    }
  }
}
于 2012-12-28T13:28:45.753 に答える