在我正在编写的代码中,我有一个名为SuccessMessage的类,其中包含字段actorType(枚举)和有效负载。我不确定制造有效载荷的类型。
如果我创建了Any类型的有效负载,我必须做很多看起来很糟糕的instanceOf类型转换,以便稍后在我的代码中处理更具体的实现。
如果我使用泛型,并使T类型的有效负载,我的其他类也必须包括类型T.例如,在我的高级特征称为Commander,我有一个名为handleSuccess的方法,它接受SuccessMessage ,它必须能够接收泛型类型T的成功消息,迫使我的指挥官也是通用类型T。
我不确定我是否必须在这两个较小的邪恶之间进行选择,或者是否有更好的方法。我必须包括一些生成有效负载的方法,因为Success Message需要不同类型的有效负载。
编辑: 泛型还有一个问题。 Commander必须能够处理许多不同类型的SuccessMessages,因此如果在handleSuccess中需要SuccessMessage [T],强制Commander成为Commander [T],那么Commander将无法处理不同类型的成功消息(我想,不是100%肯定)。
编辑2: 这是一个短暂的指挥官:
trait Commander {
def handleSuccess(message: SuccessMessage){
//based on SuccessMessage.ActorType, do different stuff
}
class SuccessMessage(val actorType: ActorType, val payload: Option[Any])
class SuccessMessage(val actorType: ActorType, val payload: Option[T])
编辑3:这是对更好地解释问题的工作流程的描述。
因此,我们需要SuccessMessage采用不同的类型。
答案 0 :(得分:2)
除非T
具有允许编译器假定其行为的某些类型的某些类型边界,否则您必须将T的实例强制转换为某种具体类型,以便将它们用于任何明确的目的。 (与Any
基本相同的问题)
您可能希望查看类型类。然后,您可以为每种类型定义某种处理程序,并使用隐式类型类实例将传入的有效内容与处理程序进行匹配。 (见https://github.com/mpilquist/simulacrum库)
编辑:此处的示例 - > https://gist.github.com/phaistos/51f0405a2f25812a5780 基本上你最终会得到一个类型类:
@typeclass trait CommanderHandler[A] {
def handle(payload: A): Unit
}
然后为每个要用作有效负载的类型创建一个实例:
implicit val handlerInt: CommanderHandler[Int] = new CommanderHandler[Int] {
def handle(payload: Int) { /* use the payload here */ }
}
然后你可以创建一个这样的函数来处理它们:
def consumePayload[T](t: T)(implicit h: CommanderHandler[T]) {
h.handle(t)
}
您为给定类型创建的隐式必须在consumePayload
的呼叫站点上可用。基本上你只是将每个类型的处理程序包装在一个漂亮的小包中。
这是迄今为止我发现的最好的模式。希望能帮助到你。如果你使用它,请确保你阅读了simulacrum的文档,你需要在创建类型类之后进行一些导入才能使它工作。
编辑:作为替代方案,您还可以通过无形的方式查看多态方法:https://github.com/milessabin/shapeless/wiki/Feature-overview:-shapeless-2.0.0#polymorphic-function-values