为什么我必须传递新关键字?

Why do I have to pass new keyword?

我有以下代码:

val fsm = TestFSMRef(new SenderCollectorFsm)

而且不明白,为什么我要传给TestFSMRef一个实例。

让我们看看TestFSMRef的定义:

object TestFSMRef {

  def apply[S, D, T <: Actor: ClassTag](
      factory: => T)(implicit ev: T <:< FSM[S, D], system: ActorSystem): TestFSMRef[S, D, T] = {
    val impl = system.asInstanceOf[ActorSystemImpl]
    new TestFSMRef(impl, Props(factory), impl.guardian.asInstanceOf[InternalActorRef], TestActorRef.randomName)
  }  

TActorClassTag 的子类型,但是如何知道 T 必须是一个对象?

Scala 是一种 object-oriented 语言。与几乎所有 object-oriented 语言一样,您只能将对象作为参数传递。此外,与大多数语言一样,类型不是对象。

所以,既然你只能传递对象,而类型不是对象,很明显你只能传递一个实例。

或者,更准确地说:存在两个独立的宇宙,类型的宇宙和的宇宙。在值的世界中,我们有一些方法将值作为圆括号(或偶尔花括号)中的参数。

在类型的世界中,我们有类型构造函数,它们将类型作为方括号中的参数。

两个宇宙恰好在一个地方相遇,那就是path-dependent种类型。

如果 SenderCollectorFsm 像这样定义为常规 class

class SenderCollectorFsm(...

那么我们必须使用 new,但是如果它被定义为 case class 就像这样

case class SenderCollectorFsm(...

然后我们可以写TestFSMRef(SenderCollectorFsm)

然而,在这两种情况下,我们传递的是 value 而不是 type,正如 Jörg W Mittag 解释的那样。虽然我可以看到 TestFSMRef(SenderCollectorFsm) 看起来好像我们正在传递一个类型,但它只是一个 shorthand 用于传递案例 class 的实例。参考Why "case class" doesn't need "new" to create a new object

还要注意 T 不是 ClassTag 的子类型,因为 type parameter clause

T <: Actor : ClassTag

由两个不同的类型约束组成 T

T <: Actor
T : ClassTag

其中 T <: Actor 确实指定 TActor 的子类型,但是 T : ClassTag 指定 T 必须具有隐式类型 class ClassTag[T] 范围内。注意类型约束 <:: 之间的区别,前者是 上限 ,而后者是 上下文边界 .