我正在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吗?
答案 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 ...
}
}
如果set
和get
实现在某种程度上是可以分解的,那么仍有改进的余地。不知道这个细节,很难说。
您还可以通过检查BooleanPref
子类型来考虑用于生成不同案例的宏,但同样需要更多有关特定案例的信息。