Scala возвращает «частичный» класс, который позже должен быть смешан с чертой - PullRequest
0 голосов
/ 28 февраля 2019

У меня есть черта

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)

Я посмотрел на макросы, и они выглядят многообещающе, но очень сложно.Мне было интересно, есть ли другой, более простой способ достижения того, чего я хочу.

1 Ответ

0 голосов
/ 28 февраля 2019

Не буквально то, что вы хотите: 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))
...