Scala(和Java)中的类和类型之间有什么区别?

soc*_*soc 53 java types scala language-design class

斯卡拉

在Scala中可以观察到类和类型之间的差异,为什么这种区别很重要?

从语言设计的角度来看,它只是一个考虑因素,还是在编写Scala时会产生"实际"影响?

或者是根本,以"固定边界"的类型系统(Nothing,Null来我的心)?

Java的

在Java中也可以识别出上面提到的考虑/差异/问题有多少?


(请参阅Type和Class之间的区别?作为语言无关的介绍.)

Jam*_*Iry 44

当你说"打字"时,我会假设你的意思是静态类型.但我很快就会讨论动态类型.

静态类型是程序的一部分的属性,可以静态证明(静态意味着"不运行它").在静态类型语言中,每个表达式都有一个类型,无论你是否写入.例如,在Cish"int x = a*b + c - d"中,a,b,c和d具有类型,a*b具有类型,a*b + c具有类型和a*b + c -d有一个类型.但是我们只用类型注释了x.在其他语言中,例如Scala,C#,Haskell,SML和F#,即使这样也没有必要.

究竟什么属性可证明取决于类型检查器.

另一方面,Scala样式类只是一组对象的规范.该规范包括一些类型信息,并包括许多实现和表示细节,如方法体和私有字段等.在Scala中,类还指定了一些模块边界.

许多语言都有类型但没有类,许多语言都有类但没有(静态)类型.

类型和类之间存在一些可观察到的差异.List [String]是一个类型,但不是类.在Scala List中是类,但通常不是类型(它实际上是更高级的类型).在C#中,List不是任何类型,在Java中它是"原始类型".

Scala提供结构类型.{def foo:Bar}表示任何可证明具有返回Bar的foo方法的对象,无论类如何.这是一种类型,但不是一类.

可以使用类型参数抽象类型.当你写def foo [T](x:T)= ...时,那么foo T体内是一个类型.但是T不是一个阶级.

类型在Scala中可以是虚拟的(即"抽象类型成员"),但今天的类不能与Scala一起虚拟(尽管有一个模板化的重要方法来编码虚拟类https://wiki.scala-lang.org/display/ SIW/VirtualClassesDesign)

现在,动态类型.动态类型是运行时在执行某些操作之前自动检查的对象的属性.在动态类型的基于类的OO语言中,类型和类之间存在很强的相关性.同样的事情发生在JVM语言上,例如Scala和Java,它们的操作只能动态检查,例如反射和转换.在这些语言中,"类型擦除"或多或少意味着大多数对象的动态类型与其类相同.或多或少.例如,通常不会擦除的数组不是这样,因此运行时可以区分Array [Int]和Array [String]之间的区别.但请记住我的广义定义"动态类型是运行时自动检查的对象的属性".使用反射时,可以将任何消息发送到任何对象.如果对象支持该消息,那么一切都会成功.因此,将所有可以像鸭子一样呱呱叫的对象称为动态类型是有道理的,即使它不是一个类.这就是Python和Ruby社区称之为"鸭子打字"的本质.另外,根据我的广义定义,即使是"zeroness"也是一种动态类型,在大多数语言中,运行时会自动检查数字以确保不会除以零.有一种非常非常少的语言可以通过将零(或非零)静态类型静态地证明.

最后,正如其他人所提到的那样,有类似int的类型没有类作为实现细节,像Null和Any这样的类型有点特殊但是COULD有类但没有类,Nothing等类型没有甚至有任何价值观,更不用说一个班级了.


Kev*_*ght 24

好吧,我会咬一口......詹姆斯有一个很好的答案,所以我会尝试不同的机智,并提供一个更实际的观点.

从广义上讲,类是可以实例化的东西.单例对象(scala)特征(Scala)和接口(Scala)通常也被认为是类.这是有道理的,因为单例仍然是实例化的(通过编译器生成的代码),并且接口可以实例化为子类的一部分.

这将我们带到第二点.在大多数面向对象语言中,类是设计的主要单元(尽管不是像javascript那样基于原型的类).多态性和子类化都是根据类来定义的.类还提供命名空间和可见性控件.


类型是一个非常不同的野兽,系统可以表达的每个可能的值都有一个或多个类型,这些有时可以等同于类,例如:

(Int) => String // both the type and class are Function1[Int,String]
"hello world" // class and type are String    
Run Code Online (Sandbox Code Playgroud)

您还可以在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"
Run Code Online (Sandbox Code Playgroud)

和非常有趣的类型根本不是类.例如,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
Run Code Online (Sandbox Code Playgroud)

Seq很有趣,因为它是一个类,但不是一个类型.更准确地说,它是一个"类型构造函数"; 在提供必要的类型参数时将构造有效类型的东西.类型构造函数的另一个术语是"更高级的类型",我个人不喜欢这个术语,因为"类型构造函数"鼓励我在提供类型方面进行思考,就像任何其他形式的参数一样 - 一个对我有用的心理模型对于斯卡拉.

"high-kinded"正确地暗示Seq具有"种类",* => *也就是说,这种符号表示Seq将采用单一类型并产生单一类型(这类似于用于描述函数的curry表示法).通过比较,这种类型Map* => * => *因为它需要两个类型参数.