Scala return "partial" class 稍后必须与特征混合

Scala return "partial" class which must be mixed-in with trait later

我有一个特点

trait DataDef {
    def getDataSource: java.sql.DataSource
}

然后是继承了这个trait的其他几个trait,比如

trait Postgres extends DataDef {
      // Postgres implementation
}

并且,

trait MySql extends DataDef {
     // For My SQL
}

还有另一个抽象class(如果需要,我可以将其转换为特征)

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
            }
    }
}

问题是重复的代码太多,看起来不像是优雅的解决方案。我应该能够 return Postgres, MySql 一次,而不需要一遍又一遍地重复代码。

我想要这样的东西:

 def getStrategy(strategyType: String) {
      // return Strategy here, like new StrategyA
 }

 def getDataDef(dataType: String) {
     // return DataDef here 
 }

然后我应该可以混合它,像这样:

 getStrategy(strategyType) with getDataDef(dataType)

我研究了宏,它们看起来很有前途,但非常复杂。我想知道是否有任何其他更简单的方法来实现我想要的。

不是您真正想要的: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))