Scala
在Scala中,类和类型之间的区别在哪里可以观察到,为什么这种区别很重要?
这只是从语言设计角度考虑的问题,还是在编写Scala程序时有“实际”影响的问题?
或者它对“保护类型系统的边界”是基本的(Nothing
,Null
让我想到了)?
Java
在Java中,有多少上面提到的考虑/差异/问题同样也可以被识别出来?
(请参见Type和Class之间的区别是什么? 作为一种非特定语言的介绍。)
Scala
在Scala中,类和类型之间的区别在哪里可以观察到,为什么这种区别很重要?
这只是从语言设计角度考虑的问题,还是在编写Scala程序时有“实际”影响的问题?
或者它对“保护类型系统的边界”是基本的(Nothing
,Null
让我想到了)?
Java
在Java中,有多少上面提到的考虑/差异/问题同样也可以被识别出来?
(请参见Type和Class之间的区别是什么? 作为一种非特定语言的介绍。)
最后,正如其他人所提到的,有一些类型(例如int)没有类作为实现细节,有一些特殊的类型(例如Null和Any)可以但没有类,还有一些类型(例如Nothing)甚至没有任何值,更别说类了。
好的,我来翻译一下... James给出了一个不错的答案,所以我将尝试一个不同的方法,给出更加平易近人的观点。
广义上来说,类是可以被实例化的东西。单例对象(Scala)、特质(Scala)和接口(Scala)通常也被认为是类。这是有道理的,因为单例仍然会通过编译器生成的代码进行实例化,而接口可以作为子类的一部分进行实例化。
这就带我们到了第二点。在大多数面向对象语言中(虽然不包括基于原型的语言,如JavaScript),类是主要的设计单位。多态性和子类化都是以类为基础定义的。类还提供了命名空间和可见性控制。
类型是一种非常不同的存在,系统可以表达的每个可能值都将具有一个或多个类型,有时这些类型可以等同于类,例如:
(Int) => String // both the type and class are Function1[Int,String]
"hello world" // class and type are String
同时,你也会发现Scala和Java之间存在一些有趣的不同点:
7 // both the class and type are Int in Scala
// in Java there's no class and the type is Integer.TYPE
println("hello world") // the return type is Unit, of class Unit
// Java has void as a type, but no corresponding class
error("oops") // the type and class are both "Nothing"
还有一些非类类型的有趣类型。例如,this.type
总是指向 this
的唯一类型。它是单个实例独有的,甚至与同一类的其他实例不兼容。
还有抽象类型和类型参数。例如:
type A // 'A' is an undetermined abstract type
// to be made concrete in a subclass
class Seq[T] { ... } // T is a type, but not a class
Seq
是一个有趣的类,但不是一个类型。更准确地说,它是一个“类型构造器”,当提供必要的类型参数时,它将构造一个有效的类型。类型构造器的另一个术语是“高阶类型”,我个人不喜欢这个术语,因为“类型构造器”鼓励我考虑像任何其他形式的参数一样提供类型 - 这是一种在Scala中表现良好的心理模型。Seq
具有“kind”,即* => *
,此符号表示Seq
将接受一个类型并产生一个类型(这类似于用于描述函数的柯里化符号)。相比之下,Map
的kind是* => * => *
,因为它需要两个类型参数。public static class Initializer<HA, HB>
,其中HA
和HB
取一些类型(由抽象类TRUE
和FALSE
表示),而不需要实例化。(仅适用于Java)我认为,类型是一组对象。如果对象o
是集合X
的成员,则对象o
是类型X
。如果集合X
是集合Y
的子集,则类型X
是子类型 of Y
。
对于每个类C(不是接口),都有一组从new C(...)
创建的对象。有趣的是,我们很少关心这个集合。(但每个对象确实属于这样一个集合,这可能是有用的事实)
对于每个类C,都有一个类型t(C)
,通常称为“类型C”,它是可以从new S(...)
创建的所有对象的集合,其中S是C或C的子类。
同样,对于每个接口I,都有一个类型t(I)
,“类型I”,它是可以从new S(...)
创建的所有对象的集合,其中S实现了I。
显然,如果类S
是类C
的子类,则类型S是类型C的子类型。接口I
同理。
有一个空类型,即空集。空类型是每种类型的子类型。
有一个包含所有对象的集合,即Object类型。它是每种类型的超类型。
到目前为止,这种形式主义相当无用。类型基本上与类或接口相同,子类型关系基本上是子类/子接口关系。这种平凡性是一件好事,语言易于理解!但是进入泛型时,会出现更复杂的类型和类型的并集和交集等操作。类型不再仅限于类和接口,子类型关系更加丰富和难以理解。
int
显然有一种类型,但没有类或接口。你也可以轻松地讨论返回 void
类型的方法,但同样没有类。 - Kevin Wright