避免使用样板来定义Scala中的getter和setter

时间:2014-07-20 05:48:02

标签: scala getter-setter

我正在Scala中开发一个桌面应用程序,它有几十个用户可以配置的配置选项。选项被定义为特征,因此单元测试和运行时应用程序可以有单独的实现:

trait Config {
  var showNotifications: Boolean
  var showOverlay: Boolean
  // ...several dozen similar options
}

单元测试的实现非常简单:

object TestConfig extends Config {
  var showNotifications: Boolean = true
  var showOverlay: Boolean = false
  // ...
}

然而,运行时使用的实现更复杂,因为它需要持久化更改并通知各种侦听器。我直接定义了getter和setter来实现这个目的;每个getter和setter都是指这样的标准方法:

class UserConfig extends Config {

  class BooleanPref(val key: String, val default: Boolean) {
    def get = {
      // ... load configuration option ...
    }
    def set(value: Boolean) = {
      // ... save configuration option ...
    }
  }

  val prefShowNotifications = new BooleanPref("showNotifications", true)
  def showNotifications: Boolean = prefShowNotifications.get
  def showNotifications_=(value: Boolean) = prefShowNotifications.set(value)

  val prefShowOverlay = new BooleanPref("showOverlay", false)
  def showOverlay: Boolean = prefShowOverlay.get
  def showOverlay_=(value: Boolean) = prefShowOverlay.set(value)

  // ... repeated several dozen times ...

}

这导致很多样板代码,看起来应该是不必要的。必须为每个配置选项单独映射getter和setter,即使它们都以完全相同的方式工作。

Scala有没有办法同时定义getter和setter? 即。而不是这个:

val prefShowNotifications = new BooleanPref("showNotifications", true)
def showNotifications: Boolean = prefShowNotifications.get
def showNotifications_=(value: Boolean) = prefShowNotifications.set(value)

是否可以分配实现getter和setter的对象或函数,如:

val showNotifications: Boolean = // something here

还是有其他方法可以避免单独定义getter和setter吗?

1 个答案:

答案 0 :(得分:2)

这样的事情应该会大大简化您的代码。

trait Config {
  sealed trait BooleanPref
  case object ShowNotificationPref extends BooleanPref
  ...

  def set(pref: BooleanPref, value: Boolean): Unit
  def get(pref: BooleanPref): Boolean
}

class UserConfig extends Config {          
  def get(pref: BooleanPref) = pref match {
     case ShowNotificationPref => ...
     case ...
  }

  def set(pref: BooleanPref, value: Boolean): Unit = pref match {
     case ShowNotificationPref => ...
     case ...
  }
}

如果setget实现在某种程度上是可以分解的,那么仍有改进的余地。不知道这个细节,很难说。

您还可以通过检查BooleanPref子类型来考虑用于生成不同案例的宏,但同样需要更多有关特定案例的信息。