我从语言设计的角度来看,为什么Scala已经删除了Java的类文字(例如String.class
)并将其替换为classOf[String]
,但后来添加了一个“类型文字”,其单例类似于{{ 1}}而不是Singleton.type
?
答案 0 :(得分:30)
这是我的合理化:
<强> classOf [T] 强>
classOf
在Predef
中定义为具有此签名的函数:
def classOf[T]: Class[T]
虽然它是由编译器实现的,但使用函数语法是可能的,而不必在语法方面创建任何特殊处理。所以这是考虑这个选项的一个原因。
像String.class
这样的替代方案意味着每个类都有一个带有字段class
的伴随对象。所以有两个问题:
class
是一个关键字,因此会导致语法需要特殊情况的问题class A
而没有一个伴随对象,那么能够引用A.class
会很奇怪,就像访问类一样1>}。<强> A.type:强>
为什么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
除了引用单例对象的类型之外不会被使用,因此它并不常见。
答案 1 :(得分:11)
实际上,它非常一致。 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代码(即使实际的实现是编译器魔术)。