2016-12-06 109 views
3

假设我想向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但正值当继承这个用例我找不到合适的解决方案,有什么帮助?

回答

5

我不确定你应该真的使用这样的含义,但也许在某些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()) 
+1

隐'strategy'参数可以与'隐VAL S = strategy'来代替,在第一线的someMethod。 – adamwy

+0

或者'import strategy._'如果你在'StringExtensionsStrategy'特性中隐藏'apply'方法。 – adamwy

+0

你可以这样做,但是在添加一些额外的隐式vals和import之后,你可以简单地写上'strategy.doSth(name)'。这就是为什么我说这可能不是一个好主意,但可能会有一些用例,并且我假定您会希望在该假设用例中尽可能减少样板文件。 –