我有一些基于 Akka 的演员系统,其中多种演员基于相同的模板,因为这些演员仅在响应值类型上有所不同。例如:
final case class Request(data: Any)
final case class Response(data: Any)
abstract class ActorTemplate[T] extends Actor {
def dataFunction: PartialFunction[Any, T]
def respond(data: T): Response
def receive: Receive = {
case Request(data) if dataFunction.isDefinedAt(data) =>
sender ! respond(dataFunction(data))
}
}
部分函数有一种方法可以避免类型擦除,这使我无法简单
def receive: Receive = {
case Request(data: T) =>
sender ! respond(data)
同时强迫我if dataFunction.isDefinedAt(data)
对模式产生警惕,我根本不喜欢它。
有什么方法可以避免显式保护?
我现在发现的唯一方法是引入一些愚蠢的提取器:
object DataExtractor {
def unapply(data: Any): Option[T] =
if (dataFunction.isDefinedAt(data)) Some(dataFunction(data)) else None
}
def receive: Receive = {
case Request(DataExtractor(data) =>
sender ! respond(data)
但也许它已经在标准库的某个地方完成了?或者也许还有其他类似于集合collect
方法的方法,但用于匹配?
结论
经过一番思考,我回到了提取器对象,并在@pagoda_5b 建议的帮助下将其移动到了一个特征中:
trait PFExtract[T] {
object PF {
def unapply(any: Any)(implicit pf: PartialFunction[Any, T]): Option[T] =
pf.lift(any)
}
}