Scala(和Java)中的类和types有什么区别?
斯卡拉
Scala中的类和types之间的区别在哪里,为什么这个区别很重要?
这只是从语言devise的angular度考虑,还是在编程Scala时有“实际”的影响?
或者是“确保types系统的界限”(根本Nothing
于我的脑海里)?
Java的
Java中还可以认识到上面提到的多less个考虑/差异/问题?
(请参阅types和类的区别是什么?作为一个语言不可知的介绍。)
当你说“types”时,我会假设你的意思是静态types。 不过我马上谈谈dynamictypes。
静态types是可以被静态certificate的程序的一部分的属性(静态意味着“不运行它”)。 在静态types语言中,每个expression式都有一个types,不pipe你是否写它。 例如,在Cish“int x = a * b + c – d”中,a,b,c和d有types,a * b有types,a * b + c有types,a * b + c -d有一个types。 但是我们只用一个types来注释x。 在其他语言中,如Scala,C#,Haskell,SML和F#,甚至不需要。
究竟哪些属性可以certificate取决于types检查器。
另一方面,Scala样式类只是一组对象的规范。 该规范包含了一些types信息,并包含了很多实现和表示细节,如方法体和私有字段等。在Scala中,类也指定了一些模块边界。
许多语言有types,但没有类,许多语言有类,但没有(静态)types。
types和类之间有几个可观察的差异。 List [String]是一个types,但不是一个类。 在斯卡拉列表是类,但通常不是一个types(它实际上是一个更高的kindedtypes)。 在C#中,列表不是任何types的types,在Java中它是一个“原始types”。
斯卡拉提供结构types。 {def foo:Bar}表示任何对象,可certificate有一个返回一个Bar的foo方法,而不pipe类是什么。 这是一种types,但不是一个类。
types可以使用types参数来抽象。 当你写def foo [T](x:T)= …时,那么在foo的内部T是一个types。 但是T不是一个阶级。
types在Scala中可以是虚拟的(即“抽象types成员”),但类今天不能用Scala虚拟化(尽pipe编码虚拟类的方式很繁琐) https://wiki.scala-lang.org/display/ SIW / VirtualClassesDesign )
现在,dynamictypes。 dynamictypes是运行时在执行某些操作之前自动检查的对象的属性。 在dynamictypes的基于类的OO语言中,types和类之间有很强的相关性。 JVM语言(如Scala和Java)上也有类似的情况,它们的操作只能dynamic检查,如reflection和投射。 在这些语言中,“types删除”或多或less意味着大多数对象的dynamictypes与其类相同。 或多或less。 例如,数组通常不会被擦除,因此运行时可以区分Array [Int]和Array [String]。 但请记住我的广义定义“dynamictypes是运行时自动检查的对象的属性”。 使用reflection时,可以将任何消息发送到任何对象。 如果对象支持这个消息,那么一切都会结束。 因此,谈论所有可以像鸭子一样动作的东西,尽pipe它不是一个阶级。 这就是Python和Ruby社区称之为“鸭子打字”的本质。 而且,根据我的广义定义,即使“zeroness”是一种dynamictypes,在大多数语言中,运行时自动检查数字以确保不会被零除。 有一种非常非常less的语言可以通过使静态types为零(或非零)来静态地certificate这一点。
最后,正如其他人所提到的那样,像int这样的types没有一个类作为实现细节,types如Null和Any有点特殊,但是可以有类而不是,types如Nothing,甚至没有任何价值,更不用说上课了。
好吧,我会咬的…詹姆斯有一个很好的答案,所以我会尝试一个不同的机智,给一个更扎实的观点。
广义而言,一个类是可以被实例化的东西 。 单例对象(Scala)特征(Scala)和接口(Scala)通常也被认为是类。 这是有道理的,因为单例仍然是实例化的(通过编译器生成的代码),一个接口可以被实例化为子类的一部分。
这给我们带来了第二点。 类是大多数面向对象语言中的主要devise单元(尽pipe不是基于原型的类似javascript)。 多态性和子类都是根据类来定义的。 类还提供名称空间和可见性控制。
types是一个非常不同的野兽,系统可以expression的每一个可能的价值将会有一个或多个types,有时这些types可以等同于类,例如:
(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"
以及真正有趣的types,根本不是类。 例如, this.type
总是指这个的唯一types。 它对于单个实例是唯一的,甚至与同一类的其他实例不兼容。
还有抽象types和types参数。 例如:
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
很有趣,因为它是一个类,但不是一个types。 更准确地说,这是一个“types构造函数”; 当提供必要的types参数时将会构造一个有效的types。 对于types构造函数来说,另一个术语是“更高级的types”,我个人不喜欢这个术语,因为“types构造函数”鼓励我从提供types的angular度思考任何其他forms的争论 – 一种心理模型,为斯卡拉。
“更高级的”意味着Seq
有一个“kind”,即* => *
,这个表示法指出Seq
将采用单一types并产生单一types(这与用于描述函数的curried表示法类似)。 通过比较, Map
的types是* => * => *
因为它需要两个types参数。
一个types本身可以是有用的,没有任何实例。 这方面的一个例子就是所谓的“幻影型”。 这里是一个Java的例子: http : //michid.wordpress.com/2008/08/13/type-safe-builder-pattern-in-java/
在这个例子中,我们有public static class Initializer<HA, HB>
,其中HA
和HB
采用某些types(由抽象类TRUE
和FALSE
),而不需要实例化。
我希望这表明types和类是不同的,types可以自己有用。
(只有Java)我会说,一个types是一组对象。 对象o
是typesX
,如果o
是集合X
的成员。 typesX
是Y
的子types ,如果集合X
是Y
的子集 。
对于每个类C(不是接口),都有一组由new C(...)
创build的对象。 有趣的是,我们很less关心这个集合。 (但是每个对象都属于这样的一个集合,这个事实可能是有用的)
对于每个类C,都有一个typest(C)
,通常称为“typesC”,它是可以new S(...)
创build的所有对象的集合,其中S是C或子类的C.
类似地,对于每个接口I,都有一个typest(I)
,即“typesI”,它是可以new S(...)
创build的所有对象的集合,其中S实现I.
显然,如果S
类是C
一个子类,Stypes就是C
types的子types
有一个空types,这是空集。 空types是每种types的子types。
有一组所有的对象,这就是Objecttypes。 这是每种types的超级types。
到目前为止,这种forms主义很无用。 types与类或接口基本相同,子types关系基本上是子类/子接口关系。 琐碎是一件好事,语言是可以理解的! 但是进入generics,types更复杂,像联合和types交叉等操作。 types不再只是类和接口,而且子types关系更加丰富和难以理解。