问题
I have the following code:
val fsm = TestFSMRef(new SenderCollectorFsm)
And do not understand, why do I have to pass to TestFSMRef
an instance.
Lets look at the definition of 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
is subtype of Actor
and ClassTag
, but how to know, that T
has to be an object?
回答1:
Scala is an object-oriented language. Like in almost all object-oriented languages, you can only pass objects as arguments. Also, like most languages, types aren't objects.
So, since you can only pass objects, and types aren't objects, it is clear that you can only pass an instance.
Or, to be more precise: there exist two separate universes, the universe of types and the universe of values. In the universe of values, we have methods which take values as arguments in round parentheses (or occasionally curly braces).
In the universe of types, we have type constructors, which take types as arguments in square brackets.
There is exactly one place where the two universes meet, and that is in path-dependent types.
回答2:
If SenderCollectorFsm
is defined as a regular class like so
class SenderCollectorFsm(...
then we have to use new
, however if it was defined as case class like so
case class SenderCollectorFsm(...
then we could write TestFSMRef(SenderCollectorFsm)
.
However in both cases we are passing a value not a type, as Jörg W Mittag explained. Although I can see how TestFSMRef(SenderCollectorFsm)
might appear as if we are passing a type, it is simply a shorthand for passing an instance of a case class. Refer to Why "case class" doesn't need "new" to create a new object
Also note that T
is not a subtype of ClassTag
, since type parameter clause
T <: Actor : ClassTag
consists of two distinct type constraints on T
T <: Actor
T : ClassTag
where T <: Actor
indeed specifies T
is a subtype of Actor
, however T : ClassTag
specifies T
has to have an implicit type class ClassTag[T]
in scope. Note the difference between type constraints <:
and :
, where former is an upper bound, whilst latter is a context bound.
来源:https://stackoverflow.com/questions/56610865/why-do-i-have-to-pass-new-keyword