Scala 'S. type и Java's.class буквальный
Интересно, почему Scala удалила литерал класса Java (например, String.class
) и заменила его на classOf[String]
, но затем добавила "литерал типа" с его Синглетами, такими как Singleton.type
вместо чего-то вроде typeOf[Singleton]
?
2 ответа:
Вот моя рационализация:
ClassOf[T]
classOf
определяется вPredef
как функция с такой сигнатурой:def classOf[T]: Class[T]
Несмотря на то, что он реализован компилятором, использование синтаксиса функции возможно без необходимости создавать какую-либо специальную обработку в терминах синтаксиса. Так что это одна из причин, чтобы рассмотреть этот вариант.
Альтернатива типа
String.class
подразумевает, что каждый класс имеет сопутствующий объект с полемclass
. Так что там есть две проблемы:
class
является ключевым словом, поэтому возникает проблема, когда синтаксис требует для него специального случая- Если вы просто создаете
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 (даже если фактическая реализация-магия компилятора).