Scala Factory Pattern根据泛型类型返回具体的类

时间:2018-09-22 22:12:13

标签: scala generics factory-pattern

我将工厂模式与泛型一起使用。想法是根据BlockType1Impl的类型(案例类型(BlockType2ImplA)创建正确的实现(BlockchainType1BlockchainType2)。我没有放置任何“类型边界”约束。

代码

在使用通用类型的apply方法查看了this example之后

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 :(得分:2)

您的代码不起作用,因为编译器不知道从何处获取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]

此模式称为类型类,它用于获取临时多态性。在您的示例中,您需要为BlockTypeFactory上定义的每个类使用多态方法findTransactions。