Scala Factory Pattern возвращает конкретный класс в зависимости от универсального типа - PullRequest
0 голосов
/ 23 сентября 2018

Я использую фабричный шаблон с генериками.Идея состоит в том, чтобы создать правильную реализацию (BlockType1Impl или BlockType2Impl) в зависимости от типа A, который является классом дела (BlockchainType1 или BlockchainType2).Я не накладываю никаких ограничений типа границ.

Код

После просмотра этого примера для метода apply с универсальными типами

trait BlockTypeFactory[A]{

  def findTransactions( blocks: Seq[A], address: String): Seq[TransactionResponse]

}


object BlockTypeFactory{
  // I want this method to return the correct implementations 
  def getBlockExplorer[A](blockType: A): BlockTypeFactory[A] = {
    blockType match {
      case type1: BlockchainType1 => new BlockTypeFactory[BlockchainType1](new BlockType1Impl)
    // error : Expression of type BlockTypeFactory[BlockType1Impl] doesn't conform with the expected type BlockTypeFactory[A]
      case type2: BlockchainType2 => new BlockType2Impl
    }
  }

def apply[A](implicit ev: BlockTypeFactory[A],blockType: A):BlockTypeFactory[A] = ev

}

Но я получаю ошибку об ожидаемом типе .Что именно не так?

Другие классы

class BlockType1Impl extends BlockTypeFactory[BlockchainType1]

class BlockType2Impl extends BlockTypeFactory[BlockchainType2]

case class BlockchainType1(...)
case class BlockchainType2(...)

fhdfjfh

1 Ответ

0 голосов
/ 23 сентября 2018

Ваш код не работает, потому что компилятор не знает, где получить неявные экземпляры BlockTypeFactory.

Для достижения вашей цели вы можете использовать классы типов.

Этоспособ расширяемый, вы можете иметь более одной фабрики на класс, если хотите (вам нужно поиграть с областью влияния), и вы можете определить стандартные фабрики для некоторых типов.

Вы можете кодировать неявные экземпляры ваших классов делвнутри объекта BlockTypeFactory, но это обычно так.

// your type class
trait BlockTypeFactory[A] {
  def create:A
} 

case class BlockchainType1()

object BlockchainType1 {
  // type 1 impl
  implicit val factory:BlockTypeFactory[BlockchainType1] = new BlockTypeFactory[BlockchainType1] {
    def create: BlockchainType1 = BlockchainType1()
  }
}

case class BlockchainType2()

object BlockchainType2 {
  // type 2 impl
  implicit val factory:BlockTypeFactory[BlockchainType2] = new BlockTypeFactory[BlockchainType2] {
    def create: BlockchainType2 = BlockchainType2()
  }
}

object BlockTypeFactory {

  // get factory
  def apply[A:BlockTypeFactory]:BlockTypeFactory[A] = implicitly[BlockTypeFactory[A]]

  // or create
  def create[A:BlockTypeFactory]:A = implicitly[BlockTypeFactory[A]].create

}

val instance1 = BlockTypeFactory[BlockchainType1].create

val instance2 = BlockTypeFactory.create[BlockchainType2]

Этот шаблон называется Type Class и используется для получения специального полиморфизма.В вашем примере вам нужен полиморфный метод findTransactions для каждого класса, определенного в BlockTypeFactory.

...