Почему я должен передать новое ключевое слово? - PullRequest
1 голос
/ 15 июня 2019

У меня есть следующий код:

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 должен быть объектом?

Ответы [ 2 ]

3 голосов
/ 15 июня 2019

Если SenderCollectorFsm определен как обычный класс, например

class SenderCollectorFsm(...

тогда мы должны использовать new, однако, если он был определен как case-класс, например

case class SenderCollectorFsm(...

тогда мы могли бы написать TestFSMRef(SenderCollectorFsm).

Однако в обоих случаях мы передаем значение , а не тип , как объяснил Йорг Миттаг. Хотя я могу видеть, как TestFSMRef(SenderCollectorFsm) может выглядеть так, как будто мы передаем тип, это просто сокращение для передачи экземпляра класса case. Обратитесь к Почему «case case» не нуждается в «new» для создания нового объекта

Также обратите внимание, что T не является подтипом ClassTag, поскольку параметр параметра типа

T <: Actor : ClassTag

состоит из двух различных типов ограничений на T

T <: Actor
T : ClassTag

, где T <: Actor действительно указывает T - это подтип Actor, однако T : ClassTag указывает, что T должен иметь неявный класс типов ClassTag[T] в области видимости. Обратите внимание на разницу между типовыми ограничениями <: и :, где первая - это верхняя граница , а вторая - контекстная граница .

3 голосов
/ 15 июня 2019

Scala - объектно-ориентированный язык. Как и почти во всех объектно-ориентированных языках, вы можете передавать объекты только в качестве аргументов. Также, как и большинство языков, типы не являются объектами.

Итак, поскольку вы можете передавать только объекты, а типы не являются объектами, ясно, что вы можете передавать только экземпляр.

Или, если быть более точным: существуют две отдельные вселенные: вселенная типов и вселенная значений . Во вселенной значений у нас есть методы, которые принимают значения в качестве аргументов в круглых скобках (или иногда в фигурных скобках).

Во вселенной типов у нас есть конструкторы типов, которые принимают типы в качестве аргументов в квадратных скобках.

Существует ровно одно место, где встречаются две вселенные, и оно относится к типу, зависящему от пути.

...