Подтвердить что ты не робот

Scala.type и Java.class literal

Интересно, с точки зрения дизайна языка, почему Scala удалил литерал класса Java (например, String.class) и заменил его на classOf[String], но затем добавил "литерал типа" с его синглонами, например Singleton.type что-то вроде typeOf[Singleton]?

4b9b3361

Ответ 1

Вот моя рационализация:

classOf [Т]

classOf определяется в Predef как функция с этой сигнатурой:

def classOf[T]: Class[T]

Хотя он реализован компилятором, использование синтаксиса функции возможно без необходимости создания какой-либо специальной обработки с точки зрения синтаксиса. Так что одна причина здесь, чтобы рассмотреть этот вариант.

Альтернатива, подобная String.class, подразумевает, что каждый класс имеет объект-компаньон с полем class. Таким образом, есть две проблемы:

  • class - это ключевое слово, поэтому возникает проблема, когда для синтаксиса для него требуется специальный случай
  • Если вы просто создаете class A без объекта-компаньона, было бы странно иметь возможность ссылаться на A.class, что было бы похоже на доступ к полю класса на компаньоне A.

A.type:

Почему typeOf[A] может ввести в заблуждение. Это похоже на вызов функции, но типы не живут в том же мире, что и результаты функции (результаты функции имеют типы, но сам тип имеет смысл только во время компиляции). Я могу приписать тип переменной:

scala> val a: A.type = A
a: A.type = [email protected]

Я не могу назначить тип, подобный возвращаемому функцией:

scala> val b = A.type
<console>:1: error: identifier expected but 'type' found.
   val b = A.type
             ^

С другой стороны, типы могут быть членами объекта:

scala> object A { type type1 = Int }
defined module A

scala> val x: A.type1 = 1
x: A.type1 = 1

Таким образом, не имеет большого значения A.type, относящегося к типу объекта A. Обратите внимание, что .type не используются для ссылок на типы одноэлементных объектов, поэтому на самом деле это не так часто.

Ответ 2

Собственно, он вполне последователен. Singleton.type является зависимым типом Singleton, а classOf[Class] является параметром типа для метода.

Рассмотрим это:

class A {
    class B
}

val a: A = new A
val b: a.B = new a.B

Дело в том, что . используется для указания того, что является членом значения. Это может быть val, a var, a def или object, а также может быть type, a class или trait.

Поскольку одноэлементный объект является значением, тогда Singleton.type отлично действует.

С другой стороны, класс не является объектом, поэтому Class.class не имеет смысла. class не существует (как значение), поэтому его невозможно получить. С другой стороны, это определение как def classOf[T]: Class[T] является простым Scala кодом (даже если фактическая реализация - это магия компилятора).