在Scala中将构造函数作为函数处理 - 如何将构造函数放在映射中?

时间:2011-05-29 06:40:13

标签: function scala constructor

我需要解析一些消息。消息的前4个字节标识消息的类型,因此,使用它,我可以实例化正确类型的对象。为了使这个有效的操作,我想我会创建一个哈希映射,其中键是前4个字节,值是对象构造函数。我可以查看构造函数并调用它。

毕竟,构造函数只是函数,将函数放在映射中应该没有任何问题。事实证明我遇到了一些困难,因为我不知道如何正确地表达对构造函数的引用。

为了通过简化示例得到具体结论,假设我们有一个消息基类MsgBase和几个子类MsgAMsgB。如果我为每个消息创建一个伴随对象并将一个工厂函数放入其中,我可以使用这些函数制作数组没有任何问题。

这是一个简化的示例,它将消息作为字符串。

class MsgBase(message: String) { }

class MsgA(message: String) extends MsgBase(message) { }

object MsgA  { def makeIt(message: String): MsgA = new MsgA(message)  }

MsgB相似。然后我可以制作地图:

val cm = Map[String, (String) => MsgBase]("a" -> MsgA.makeIt, "b" -> MsgB.makeIt)

val myMsg = cm("a")("a.This is the message")

看起来我应该能够直接在构建地图的表达式中引用消息对象构造函数,而不是使用随播对象中的普通函数,但我还没有想出任何表达方式。有办法吗?

3 个答案:

答案 0 :(得分:12)

尝试

"a" -> (new MsgA(_))

(需要所有括号)。

即使这不起作用,您当然也可以明确定义函数:

"a" -> ( (s: String) => new MsgA(s) )

答案 1 :(得分:3)

对于这种情况,最好使用案例类,它会自动为您提供创建新对象的功能。

scala> case class MsgA(message: String) extends MsgBase(message)
scala> case class MsgB(message: String) extends MsgBase(message)

所以你可以通过名字来引用它们,而不需要任何语法上的开销

scala> val m = Map("a"->MsgA, "b"->MsgB)
m: scala.collection.immutable.Map[java.lang.String,scala.runtime.AbstractFunction1[java.lang.String,Product with MsgBase]] = Map((a,<function1>), (b,<function1>))

scala> m("a")("qqq")                              
res1: Product with MsgBase = MsgA(qqq)

作为替代方法,您可以手动覆盖apply方法创建伴随对象。有关详细信息,请参阅Programming scala, chapter 6

答案 2 :(得分:2)

val cm = Map[String, (String) => MsgBase]("a" -> (new MsgA(_)), "b" -> (new MsgB(_)))