Scala隐式类和继承
问题描述:
假设我想向String类添加一些方法。但是应该应用的具体隐式类在运行时已知(策略模式)。比方说,我们有Scala隐式类和继承
trait StringExtensions {
def doSth(str: String): String
}
class Strategy1 extends StringExtensions {
override def doSth(str: String): String = "a"
}
class Strategy2 extends StringExtensions {
override def doSth(str: String): String = "b"
}
现在我的客户端代码如下所示:
def someMethod(strategy: StringExtensions) : String{
val name = "Pawel"
return strategy.doSth(name)
}
...
String ret = someMethod(new Strategy1())
,但我想有这样的代码:
def someMethod(strategy: StringExtensions) : String{
val name = "Pawel"
return name.doSth() // Here is the tricky line
}
...
String ret = someMethod(new Strategy1())
我打得有点与implicits但正值当继承这个用例我找不到合适的解决方案,有什么帮助?
答
我不确定你应该真的使用这样的含义,但也许在某些DSL这可能是一个有效的用例。
class StringExtensions(str: String, strategy: StringExtensionsStrategy) {
def doSth() = strategy.doSth(str)
}
trait StringExtensionsStrategy extends (String => StringExtensions) {
final def apply(str: String) = new StringExtensions(str, this)
def doSth(str: String): String
}
class Strategy1 extends StringExtensionsStrategy {
override def doSth(str: String) = "a"
}
class Strategy2 extends StringExtensionsStrategy {
override def doSth(str: String) = "b"
}
def someMethod(implicit strategy: StringExtensionsStrategy) = {
val name = "Pawel"
name.doSth()
}
val ret: String = someMethod(new Strategy1())
作为评价所提到的,可替换的编码将是这样:
class StringExtensions(str: String, strategy: StringExtensionsStrategy) {
def doSth() = strategy.doSth(str)
}
trait StringExtensionsStrategy {
implicit final def apply(str: String) = new StringExtensions(str, this)
def doSth(str: String): String
}
class Strategy1 extends StringExtensionsStrategy {
override def doSth(str: String) = "a"
}
class Strategy2 extends StringExtensionsStrategy {
override def doSth(str: String) = "b"
}
def someMethod(strategy: StringExtensionsStrategy) = {
import strategy._
val name = "Pawel"
name.doSth()
}
val ret: String = someMethod(new Strategy1())
隐'strategy'参数可以与'隐VAL S = strategy'来代替,在第一线的someMethod。 – adamwy
或者'import strategy._'如果你在'StringExtensionsStrategy'特性中隐藏'apply'方法。 – adamwy
你可以这样做,但是在添加一些额外的隐式vals和import之后,你可以简单地写上'strategy.doSth(name)'。这就是为什么我说这可能不是一个好主意,但可能会有一些用例,并且我假定您会希望在该假设用例中尽可能减少样板文件。 –