我有以下代码:
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)
}
T
是Actor
和ClassTag
的子类型,但是如何知道T
必须是对象呢?
答案 0 :(得分:3)
Scala是一种面向对象的语言。与几乎所有面向对象的语言一样,您只能将对象作为参数传递。而且,像大多数语言一样,类型也不是对象。
因此,由于您只能传递对象,而类型不是对象,因此很显然,您只能传递实例。
或者,更准确地说:存在两个单独的Universe,即 types 的宇宙和 values 的宇宙。在值的宇宙中,我们有一些方法将值作为圆括号(或有时用大括号)中的参数。
在类型宇宙中,我们有类型构造函数,该构造函数将类型作为方括号中的参数。
两个Universe恰好在一个地方相遇,并且是依赖于路径的类型。
答案 1 :(得分:3)
如果SenderCollectorFsm
被定义为像这样的常规类
class SenderCollectorFsm(...
然后我们必须使用new
,但是如果它像这样定义为case类
case class SenderCollectorFsm(...
然后我们可以写TestFSMRef(SenderCollectorFsm)
。
但是,正如JörgW Mittag解释的那样,在两种情况下,我们都传递的是值,而不是类型。尽管我可以看到TestFSMRef(SenderCollectorFsm)
看起来像我们在传递类型一样,但是它只是传递案例类实例的简写。请参阅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
确实指定T
是Actor
的子类型,但是T : ClassTag
指定T
必须具有隐式类型类ClassTag[T]
在适用范围。注意类型约束<:
和:
之间的区别,其中前者是上限,而后者是上下文限制。