Scala 'S. type и Java's.class буквальный


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

2 30

2 ответа:

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

ClassOf[T]

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

def classOf[T]: Class[T]

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

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

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

A. тип:

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

scala> val a: A.type = A
a: A.type = A$@c21a68

Я не могу назначить тип, как это возвращается функцией:

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 не используются вне ссылки на типы одноэлементных объектов, так что это не совсем так частый.

На самом деле, это вполне последовательно. Singleton.type - зависимый тип Singleton, а classOf[Class] - параметр типа метода.

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

class A {
    class B
}

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

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

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

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