Simple Scala getter/setter override

后端 未结 1 662
独厮守ぢ
独厮守ぢ 2021-01-17 23:35

Let\'s say we have a class with a \'name\' property:

class SuperFoo(var name: String) 

If I wish to override this, to eg add some locking a

相关标签:
1条回答
  • 2021-01-18 00:15

    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:

    1. Favor composition over inheritance (a classic).
    2. Change the variable name, make it private and write accessor in the super-class (see below).
    3. 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
        }
      }
    }
    
    0 讨论(0)
提交回复
热议问题