我目前正在使用Cay Horstmann的(优秀)Scala For the Impatient (2nd Edition)自学Scala。 第11章练习11 的任务是使用 extends Dynamic 编写一个类,它允许获取和设置系统属性,其用法如下:
val props = new DynamicProps(System.getProperties)
val javaHome = props.java.home
props.set.some.property = "somevalue"
我能够使用 selectDynamic 来获取属性(虽然我认为解决方案很笨重并需要改进):
import scala.language.dynamics
class DynamicProps(val props: java.util.Properties) extends Dynamic {
def selectDynamic(name:String): DPropHelper = {
new DPropHelper(name, props)
}
}
class DPropHelper(val name: String, val props: java.util.Properties) extends Dynamic {
def selectDynamic(name:String): DPropHelper = {
new DPropHelper(this.name + "." + name, props)
}
override def toString: String = props.getProperty(name)
}
但是我完全失去了如何使用相应的 updateDynamic ,试过这个: import scala.language.dynamics
class DynamicProps(val props: java.util.Properties) extends Dynamic {
def updateDynamic(name: String)(value: String): DPropHelper = {
new DPropHelper(name, props)
}
def update(key: String, property: String) = {
println(s"DynamicProps update(${key}, ${property}) called")
}
def selectDynamic(name:String): DPropHelper = {
new DPropHelper(name, props)
}
}
class DPropHelper(val name: String, val props: java.util.Properties) extends Dynamic {
def updateDynamic(name: String)(value: String): DPropHelper = {
new DPropHelper(this.name + "." + name, props)
}
def selectDynamic(name:String): DPropHelper = {
new DPropHelper(this.name + "." + name, props)
}
def update(key: String, property: String) = {
println(s"DPropHelper update(${key}, ${property}) called")
}
override def toString: String = props.getProperty(name)
}
我非常确定我不需要帮助程序类,并且可以通过构建"堆栈"来获得相同的效果。本地列表中的路径值并返回 this ,或者只是递归地构建新的 DynamicProps 。
我的问题是,我怎么设法使用 updateDynamic 来最终触发更新操作 - 我的上述测试表明, update()方法都没有火。
修改 - 可能的解决方案
在Rubber Duck Debugging的最佳状态中,我提出了一个可能的解决方案。现在这已经按预期工作了,虽然我会欢迎有关风格改进的建议,因为这仍然感觉非常笨重:
import scala.language.dynamics
class DynamicProps(val props: java.util.Properties) extends Dynamic {
def updateDynamic(name: String)(value: String): DPropHelper = {
new DPropHelper(name, props)
}
def selectDynamic(name:String): DPropHelper = {
new DPropHelper(name, props)
}
}
class DPropHelper(val name: String, val props: java.util.Properties) extends Dynamic {
def updateDynamic(name: String)(value: String): Unit = {
props.setProperty(this.name + "." + name, value)
}
def selectDynamic(name:String): DPropHelper = {
new DPropHelper(this.name + "." + name, props)
}
override def toString: String = props.getProperty(name)
}
和测试
import org.scalatest.{FlatSpec, Matchers}
class DynamicPropsTest extends FlatSpec with Matchers {
"property" should "be retrievable" in {
val instance = new DynamicProps(System.getProperties)
val result = instance.java.home
result.toString should be (System.getProperties.getProperty("java.home"))
}
"property" should "be settable" in {
val instance = new DynamicProps(System.getProperties)
instance.fred.mary.jane = "alice"
System.getProperties.getProperty("fred.mary.jane") should be ("alice")
}
}