Class、Scala 中的对象、特征、密封特征
Class, Object, Trait, Sealed Trait in Scala
我来自 OOP
背景,想澄清我对 Object
、Classes
、Trait
、Sealed Trait
和 [=16= 的看法] 在 Scala
中,我在下面写下到目前为止我对它的理解:
我们创建 Object
,当我们想在其中编写一些实用函数时,我们可以直接访问它,而无需使用 "new" 关键字,如 "Static" classes在 Java.
我们创建 Classes
,当我们为动词编码时表示一个对象,它的行为封装与我们在 Java 中为 classes 编码相同,我们使用 [= 实例化它38=]关键字。
当我们想编写与 Java
.
中的抽象 classes 相同的代码时,我们创建 Trait
当我们想要实现与 Java 中相同枚举的功能时,我们创建 Sealed Trait
。
我们创建 Case classes
当我们可以预期这个 class 将来可以用于模式匹配类似于 Java.
中的 instanceOf
我对这些的理解是否正确?
如果您用 OOP 的眼光来看,您所说的大部分事实或多或少都是正确的。但我们对他们有更多。
对象
从函数式编程的角度来看,Scala 中的对象可以看作是模块。它们确实用于聚合您称为 "utility functions" 的类似类型的函数。但它们还有其他含义。
一个 object
可以被看作是一个单例对象,因为你可以有一个 object
继承一个特定的 trait
或 class
.
trait Bird
object Duck extends Bird
你还有伴随对象的概念。这是一个具有与 class 相关的模块函数的对象,您甚至可以从 class.
引用对象的 private
成员
class Dog {
def eat(food: Food) = Dog.preferredFoods.contains(food)
}
object Dog {
private val preferredFoods = List(Ribeye, DogFood, Banana)
def walk(dog: Dog) = ???
}
Class
关于 class 你是对的。它们与 Java 概念非常接近。
特质
在 Scala 中查看 trait
的一种方法是 abstract class
。但请注意,您也可以在 Scala 中使用 abstract class
,其行为与 Java 中的相同。那有什么区别呢?
正如评论中指出的,几个 trait
可以混合在一起。
如果完全抽象,trait
s也可以看作是Java interface
,也就是说所有方法都是抽象的,就像Java一样。事实上,如果您的目标是与 Java 互操作,那就是声明 interface
.
的方式
A sealed trait
只是一种告诉编译器您不会有任何 classes 或其他继承此特征的方式,除了同一文件中的特征。正如您针对 case classes 指出的那样,这用于模式匹配的目的,因此编译器能够判断模式匹配是否详尽并发出警告。但也要注意 Scala 有 enum
.
案例class
大小写 classes 可以与 sealed trait
一起用于模式匹配。但是 case class
更像是 "value class"。 case
使编译器生成一堆样板代码,因此您不必这样做。
您有一个自动 "companion object",因此您可以在没有 new
的情况下使用自动生成的 apply
函数实例化对象。
您有自动 hashCode
、equals
、toString
和 copy
实施。并且所有构造函数的参数都有自动 val
s。
scala> case class Room(area: Int)
defined class Room
scala> var r = Room(16)
r: Room = Room(16)
scala> r.hashCode
res2: Int = 1313771839
scala> r == Room(16)
res3: Boolean = true
scala> r == Room(15)
res4: Boolean = false
scala> r.toString
res5: String = Room(16)
scala> r.area
res6: Int = 16
scala> case class Point(x: Int, y: Int)
defined class Point
scala> val p = Point(1, 1)
p: Point = Point(1,1)
scala> val p1 = p.copy(y = 0)
p1: Point = Point(1,0)
我来自 OOP
背景,想澄清我对 Object
、Classes
、Trait
、Sealed Trait
和 [=16= 的看法] 在 Scala
中,我在下面写下到目前为止我对它的理解:
我们创建 Object
,当我们想在其中编写一些实用函数时,我们可以直接访问它,而无需使用 "new" 关键字,如 "Static" classes在 Java.
我们创建 Classes
,当我们为动词编码时表示一个对象,它的行为封装与我们在 Java 中为 classes 编码相同,我们使用 [= 实例化它38=]关键字。
当我们想编写与 Java
.
Trait
当我们想要实现与 Java 中相同枚举的功能时,我们创建 Sealed Trait
。
我们创建 Case classes
当我们可以预期这个 class 将来可以用于模式匹配类似于 Java.
我对这些的理解是否正确?
如果您用 OOP 的眼光来看,您所说的大部分事实或多或少都是正确的。但我们对他们有更多。
对象
从函数式编程的角度来看,Scala 中的对象可以看作是模块。它们确实用于聚合您称为 "utility functions" 的类似类型的函数。但它们还有其他含义。
一个 object
可以被看作是一个单例对象,因为你可以有一个 object
继承一个特定的 trait
或 class
.
trait Bird
object Duck extends Bird
你还有伴随对象的概念。这是一个具有与 class 相关的模块函数的对象,您甚至可以从 class.
引用对象的private
成员
class Dog {
def eat(food: Food) = Dog.preferredFoods.contains(food)
}
object Dog {
private val preferredFoods = List(Ribeye, DogFood, Banana)
def walk(dog: Dog) = ???
}
Class
关于 class 你是对的。它们与 Java 概念非常接近。
特质
在 Scala 中查看 trait
的一种方法是 abstract class
。但请注意,您也可以在 Scala 中使用 abstract class
,其行为与 Java 中的相同。那有什么区别呢?
正如评论中指出的,几个 trait
可以混合在一起。
如果完全抽象,trait
s也可以看作是Java interface
,也就是说所有方法都是抽象的,就像Java一样。事实上,如果您的目标是与 Java 互操作,那就是声明 interface
.
A sealed trait
只是一种告诉编译器您不会有任何 classes 或其他继承此特征的方式,除了同一文件中的特征。正如您针对 case classes 指出的那样,这用于模式匹配的目的,因此编译器能够判断模式匹配是否详尽并发出警告。但也要注意 Scala 有 enum
.
案例class
大小写 classes 可以与 sealed trait
一起用于模式匹配。但是 case class
更像是 "value class"。 case
使编译器生成一堆样板代码,因此您不必这样做。
您有一个自动 "companion object",因此您可以在没有 new
的情况下使用自动生成的 apply
函数实例化对象。
您有自动 hashCode
、equals
、toString
和 copy
实施。并且所有构造函数的参数都有自动 val
s。
scala> case class Room(area: Int)
defined class Room
scala> var r = Room(16)
r: Room = Room(16)
scala> r.hashCode
res2: Int = 1313771839
scala> r == Room(16)
res3: Boolean = true
scala> r == Room(15)
res4: Boolean = false
scala> r.toString
res5: String = Room(16)
scala> r.area
res6: Int = 16
scala> case class Point(x: Int, y: Int)
defined class Point
scala> val p = Point(1, 1)
p: Point = Point(1,1)
scala> val p1 = p.copy(y = 0)
p1: Point = Point(1,0)