【问题标题】:Akka Actor - Receive Pattern Match by Generic TypeAkka Actor - 按通用类型接收模式匹配
【发布时间】:2018-09-30 05:22:17
【问题描述】:

我有一个泛型 Actor 类,我想与接收方法中的泛型类型进行模式匹配。

例如:

class Test[S] extends Actor {
  override def receive: Receive = {
    case _: S => println("yes")
    case _ => println("no")
  }
}

val ac = system.actorOf(Props(new Test[Int]))
ac ! "abc" // expect print "no" 
ac ! 3     // expect print "yes"

但是,它似乎永远不会进入第二种情况,并且总是打印出“是”...

如何让它打印“否”?

【问题讨论】:

  • 我的错...现在修复了。

标签: scala pattern-matching akka actor


【解决方案1】:

问题

您刚刚偶然发现了一种叫做类型擦除的东西。这意味着,泛型类型信息在编译期间被删除(JVM 不知道泛型)。所以在运行时,你的 actor 将如下所示:

class Test extends Actor {
  override def receive: Receive = {
    case _: Object => println("yes")
    case _ => println("no")
  }
}

这就是为什么ac ! "abc"ac ! 3 将始终与第一种情况匹配。

幸运的是,Scala 提供了有助于克服这个问题的机制。你可以阅读更多关于他们的信息in this articlein the docs

解决方案

tldr;你可以找到一个工作示例here, on Scastie

您应该使用其中一种机制:ClassTag。您可以将其视为一个对象,它包含运行时编译时可用的所有信息。

import scala.reflect.ClassTag

object Main extends App {

  class Test[S](implicit ct: ClassTag[S]) extends Actor {
    override def receive: Receive = {
      case _: S => println("yes")
      case _ => println("no")
    }
  }

  val system = ActorSystem()

  val ac = system.actorOf(Props(new Test[Int]))
  ac ! "abc" // expect print "no"
  ac ! 3 // expect print "yes"

  system.terminate()

}

您可能想知道在哪里可以找到 ClassTag[T] 的隐式实例。幸运的是,编译器会按需提供。

奖励:您可以重写class Test[S](implicit ct: ClassTag[S]) extends Actor 以使用所谓的Context Boundsclass Test[S: ClassTag] extends Actor

您可以按如下方式阅读此签名:

一个类 Test 由类型 S 参数化,在隐式范围内有可用的 ClassTag[S]

【讨论】:

  • 非常感谢您提供工作示例和大量资源 :) 我不了解 Scastie。很酷!
  • 顺便说一句,trait 也有类型标签吗?
  • 比如trait Test[S]??
  • 不客气 :)!如果 actor 是 trait,您可以通过调用 classTag 方法以不同的方式获取 ClassTag:scastie.scala-lang.org/tVa9ENThQlydtetmpS0iGg
猜你喜欢
  • 1970-01-01
  • 2014-03-05
  • 2018-06-20
  • 2016-07-14
  • 1970-01-01
  • 2014-01-08
  • 2012-02-21
  • 2017-11-23
  • 2015-04-15
相关资源
最近更新 更多