【问题标题】:Scala Factory Pattern return the concrete class depending on the generic typeScala 工厂模式根据泛型类型返回具体类
【发布时间】:2020-11-25 08:10:23
【问题描述】:

我将工厂模式与泛型一起使用。这个想法是根据 A 的类型创建正确的实现(BlockType1ImplBlockType2Impl),这是一个案例类(BlockchainType1BlockchainType2)。我没有设置任何类型边界约束。

代码

查看this example 对泛型类型的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(...)

【问题讨论】:

  • 宁可使用typeclass机制来表示工厂,实例为A type

标签: scala generics factory-pattern


【解决方案1】:

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

【讨论】:

  • 知道了。我的特质声明是错误的。当您传递一个案例类 BlockchainType 时,工厂将返回 BlockTypeImpl,它扩展了工厂 trait。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-17
  • 2021-07-26
  • 1970-01-01
  • 2018-01-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多