Class、Scala 中的对象、特征、密封特征

Class, Object, Trait, Sealed Trait in Scala

我来自 OOP 背景,想澄清我对 ObjectClassesTraitSealed 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 继承一个特定的 traitclass.

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 可以混合在一起。

如果完全抽象,traits也可以看作是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 函数实例化对象。

您有自动 hashCodeequalstoStringcopy 实施。并且所有构造函数的参数都有自动 vals。

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)