简单的Scala getter / setter覆盖

时间:2012-12-28 12:18:57

标签: scala inheritance properties setter getter

假设我们有一个带有'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 

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

1 个答案:

答案 0 :(得分: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编译时没有任何问题,则getter不会,因为编译器会将其视为super.name.apply()(字符串可以通过隐式转换获得此方法)。

我看到了几个选项:

  1. 赞成合成而不是继承(经典)。
  2. 更改变量名称,将其设为私有,并在超类中编写访问器(见下文)。
  3. 诉诸于反思/手册名称umangling voodoo。
  4. 我会选择#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
        }
      }
    }