Scala返回“部分”类,以后必须与特征混合

时间:2019-02-28 00:11:55

标签: scala types traits scala-macros

我有一个特征

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

问题在于,有太多的代码被重复,而且看起来并不太优雅。我应该只能返回一次PostgresMySql,并且不必一遍又一遍地重复代码。

我想要类似的东西

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

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

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

 getStrategy(strategyType) with getDataDef(dataType)

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

1 个答案:

答案 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))