Emi*_*elt 0 oop generics scala type-inference
我想要完成什么
我想利用策略模式,而策略类有类型参数.
代码是什么样的
假设我有以下通用抽象策略类:
abstract class Strategy[T, V]() {
def doSomething(x: Int): V
def unDoSomething(x: V): T
}
Run Code Online (Sandbox Code Playgroud)
我现在得出两个具体的策略:
class StrategyOne() extends Strategy[Int, String] {
def doSomething(x: Int): String = { x.toString() }
def unDoSomething(x: String): Int = { x.toInt }
}
class StrategyTwo() extends Strategy[Double, List[Int]] {
def doSomething(x: Int): List[Int] = { List(x, 10, 20)}
def unDoSomething(x: List[Int]): Double= { x.reduceLeft(_ + _) + 0.1 }
}
Run Code Online (Sandbox Code Playgroud)
现在,我们有一个使用该策略的类:
class Worker[T, V](strategy: Strategy[T, V]) {
def run() {
val res = strategy.doSomething(5) //res is a T
val res2 = strategy.unDoSomething(res) //res2 is a V
println(res2)
}
}
Run Code Online (Sandbox Code Playgroud)
正如所料,我现在能够使用明确类型实例化新工作者:
val worker1 = new Worker(new StrategyOne())
val worker2 = new Worker(new StrategyTwo())
Run Code Online (Sandbox Code Playgroud)
问题
但是,我也想利用某种动态策略选择,如下所示:
val strategies = Map("one" -> new StrategyOne(), "two" -> new StrategyTwo())
val worker = new Worker(strategies(args(0)))
Run Code Online (Sandbox Code Playgroud)
当然,编译器告诉我,我想要的是不可能的,因为不能推断出任何类型.
题
我知道这个星座是不幸的,但我需要的类型T和V内部Worker.是否有可能使这种模式适用于这种特定情况?
抽象类型成员应该在这里帮助你而不仅仅是输入参数.实际上,你大多想要绕过Strategys,而不必过多关注他们的两种类型(包括将它们放在地图中).在某一点(在Worker),你需要类型.
因此,我建议如下(你或许应该给予更多的描述性的名称V,并T在这个模型中,但我无法弄清楚他们的意思,所以我把它们作为是):
abstract class Strategy {
type T
type V
def doSomething(x: Int): V
def unDoSomething(x: V): T
}
class StrategyOne extends Strategy {
type T = Int
type V = String
def doSomething(x: Int): String = {...}
def unDoSomething(x: String): Int = {...}
}
class StrategyTwo extends Strategy {
type T = Double
type V = List[Int]
def doSomething(x: Int): List[Int] = {...}
def unDoSomething(x: List[Int]): Double= {...}
}
class Worker(strategy: Strategy) {
def run(): Unit = {
val res = strategy.doSomething(5) //res is a strategy.T
val res2 = strategy.unDoSomething(res) //res2 is a strategy.V
println(res2)
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,类型res和res2推断.但是,如果你需要写下他们的类型,他们就是,strategy.T并且strategy.V正如我在评论中所写的那样(路径依赖类型,如果你想谷歌这个概念).
您仍然可以轻松创建策略:
val worker1 = new Worker(new StrategyOne)
val worker2 = new Worker(new StrategyTwo)
Run Code Online (Sandbox Code Playgroud)
现在你也可以这样做:
val strategies = Map("one" -> new StrategyOne, "two" -> new StrategyTwo)
val worker = new Worker(strategies(args(0)))
Run Code Online (Sandbox Code Playgroud)
按照你的要求.这一切都很好听.
| 归档时间: |
|
| 查看次数: |
119 次 |
| 最近记录: |