类,对象,特征,Scala中的密封特征

2022-09-03 13:42:12

我来自背景,并希望清除我对 , 、 和 的想法,我正在写下我迄今为止对它的理解:OOPObjectClassesTraitSealed TraitCase ClassesScala

当我们想在其中编写一些实用程序函数时,我们创建了 ,我们可以直接访问它,而无需使用“new”关键字,例如Java中的“Static”类。Object

当我们为动词编码时,我们创建意味着一个对象,它的行为封装与我们在Java中为类编码的行为相同,我们使用“new”关键字实例化它。Classes

当我们想要与 中的抽象类相同的代码时,我们就会进行创建。TraitJava

当我们想要在Java中实现与Enum相同的功能时,我们就会创建。Sealed Trait

我们创建时,我们可以期望将来可以将此类用于模式匹配,类似于Java中的实例Of。Case classes

我对所有这些的理解是否正确?


答案 1

如果你用OOP的眼光来研究它们,你对你所说的大多数事实或多或少是正确的。但我们对他们还有更多。

对象

Scala中的对象可以从函数式编程的角度看作是模块。它们确实用于聚合您称为“实用程序函数”的类似类型的函数。但它们也有其他含义。

可以将其视为单例对象,因为您可以拥有 继承特定 或 .objectobjecttraitclass

trait Bird
object Duck extends Bird

您还有伴随对象的概念。这是一个具有与该类相关的模块函数的对象,您甚至可以从该类中引用该对象的成员。private

class Dog {
  def eat(food: Food) = Dog.preferredFoods.contains(food)
}

object Dog {
  private val preferredFoods = List(Ribeye, DogFood, Banana)
  def walk(dog: Dog) = ???
}

你对课程的看法是正确的。它们与Java概念非常接近。

特性

在 Scala 中查看 a 的一种方法是作为 .但请注意,您也可以在Scala中拥有一个,其行为与Java中的行为相同。那么有什么区别呢?traitabstract classabstract class

正如注释中所指出的,可以将几个s混合在一起。trait

如果它是完全抽象的,那么s也可以被视为Java,也就是说所有方法都是抽象的,就像Java一样。实际上,如果您的目标是与 Java 互操作,这就是声明 .traitinterfaceinterface

A 只是一种告诉编译器,除了同一文件中的类或其他特征之外,您不会有任何继承此类或其他特征的方法。正如您所指出的关于 case 类时,这起到了模式匹配的目的,因此编译器能够通过警告来判断模式匹配是否详尽无遗。但也要注意斯卡拉有.sealed traitenum

案例类

Case 类可以与 一起使用,以实现模式匹配。但 a 更像是一个“值类”。这使得编译器生成一堆样板代码,因此您不必这样做。sealed traitcase classcase

您有一个自动的“伴随对象”,因此您可以使用自动生成的函数在没有 的情况下实例化对象。newapply

您有自动 、 和 实现。并且所有构造函数的参数都有自动 s。hashCodeequalstoStringcopyval

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)

答案 2