scala动态确定类型
我想创建对象实例,其类型由运行时数据决定:scala动态确定类型,scala,Scala,我想创建对象实例,其类型由运行时数据决定: trait Business case class Business1() extends Business case class Business2() extends Business object Business { def fromData(data:Array[Byte]): Business = data(0) match { case 1 => new Business1 case 2 => new
trait Business
case class Business1() extends Business
case class Business2() extends Business
object Business {
def fromData(data:Array[Byte]): Business = data(0) match {
case 1 => new Business1
case 2 => new Business2
case _ => throw new RuntimeException("data error")
}
}
上面的代码可以完成它的工作,但有一个问题,它是关闭的。每当我实现一个新的业务
子类时,我都必须修改业务
case 3 => new Business3
如何定义Business.fromData
一次,然后在不注册的情况下添加Business3
,Business4
编辑
我终于意识到这是一个完美的多方法的用例,也就是说,基于某个参数的函数进行调度。因此,更一般的问题应该是“如何在scala中实现多重方法”?我相信设计模式的存在仅仅是因为语言能力,这就是为什么我不愿意接受基于工厂的答案。这并不能解决您的问题,但如果您将业务
作为一种“密封”特征,那么编译器将在更新fromData
之前捕获任何非详尽的匹配:
sealed trait Business
case class Business1() extends Business
case class Business2() extends Business
biz match {
case Business1 => println("Business1")
}
…将导致
warning: match is not exhaustive!
missing combination Business2
你也可以这样做。虽然我不确定这是否比比赛情况更好。这取决于你想做什么
class Business {
override def toString = "Business"
}
val factories: Map[Int, () => Business] = Map(
1 -> (() => new Business {
override def toString = "Business1"
}),
2 -> (() => new Business {
override def toString = "Business2"
}),
3 -> (() => new Business {
override def toString = "Business3"
})
)
object Business {
def fromData(data: Array[Byte]): Business = factories(data(0))()
}
val b = Business.fromData(Array(1,1,2))
println(b)
经典答案是使用注册工厂,即抽象工厂
因此,考虑到上面的层次结构,您可以创建一个“工厂”映射,就像在另一个答案中显示的那样,但您也可以创建对象创建者的平行层次结构,并在启动时注册它们,如下所示:
trait BusinessCreator {
def createBusiness() : Business
}
object BusinessCreator1() extends BusinessCreator {
override def createBusiness() : Business = new Business1()
factories += "1" -> this
}
//etc.
另一种更具“伸缩性”的方法是跳过并行层次结构,只在工厂对象中注册一个creator函数,从一个伴生对象到每个类,但想法是一样的。这个呢
val factories = collection.mutable.Map(
1 -> new Function0[Business] {
private[this] lazy val single = new Business {
override def toString = "Business1"
}
override def apply() = single
}
,2 -> new Function0[Business] {
private[this] lazy val single = new Business {
override def toString = "Business2"
}
override def apply() = single
}
,3 -> new Function0[Business] {
private[this] lazy val single = new Business {
override def toString = "Business3"
}
override def apply() = single
}
)
我会因为建议java反射而下地狱吗?:)<代码>工厂
仍处于关闭状态这将不起作用,因为“BusinessCreator”实例是延迟创建的-在引用它之前它不会被实例化。因此,您需要引用所有的创建者,这也是一个封闭的过程。