我有一个特征
trait DataDef {
def getDataSource: java.sql.DataSource
}
然后是继承该特征的其他几个特征
trait Postgres extends DataDef {
// Postgres implementation
}
和
trait MySql extends DataDef {
// For My SQL
}
和另一个抽象类(如果需要,我可以将其转换为特征)
abstract class Strategy[T](strategyType: String) {
self: DataDef =>
def lookup(): Stream[T] = {
// use self.getDataSource and strategyType here
}
}
通过这种方式,我可以将策略和数据的代码分开。例如,
class StrategyA extends Strategy[Int]("typeA") {
self: DataDef =>
// implementation of this strategy
}
现在,我要做的是将这两个连接在一起,以便当用户传递某些strategyType和DataDef类型时,我可以传递相关的对象。到目前为止,我有:
class getStrategy(strategyType: String, dataType: String) {
strategyType match {
case "typeA" =>
dataType match {
case "postgres" => return StrategyA with Postgres
case "mysql" => return StrategyA with MySql
}
case "typeB" =>
dataType match {
case "postgres" => return StrategyB with Postgres
case "mysql" => return StrategyB with MySql
}
}
}
问题在于,有太多的代码被重复,而且看起来并不太优雅。我应该只能返回一次Postgres
,MySql
,并且不必一遍又一遍地重复代码。
我想要类似的东西
def getStrategy(strategyType: String) {
// return Strategy here, like new StrategyA
}
def getDataDef(dataType: String) {
// return DataDef here
}
然后我应该可以将其混合,像这样:
getStrategy(strategyType) with getDataDef(dataType)
我研究了宏,它们看起来很有前途,但非常复杂。我想知道是否还有其他更简单的方法来实现自己想要的目标。
答案 0 :(得分:2)
并不是您想要的:with
生活在类型世界中,而不是在价值世界中,并且类型不能从方法中返回。
但是,如果您通过继承而不是继承来做,则可以进行例如
abstract class Strategy[T](strategyType: String, self: DataDef) {
// optional
// import self._
def lookup(): Stream[T] = {
// use self.getDataSource and strategyType here
}
}
class StrategyA(self: DataDef) extends Strategy[Int]("typeA", self) {
// implementation of this strategy
}
def getStrategy(strategyType: String): DataDef => Strategy {
// return e.g. new StrategyA(_)
}
def getDataDef(dataType: String) {
// return DataDef here
}
然后
getStrategy(strategyType)(getDataDef(dataType))