java - Scala 中的类、对象、特征、密封特征

标签 java scala oop functional-programming

我来自 OOP 背景,想澄清我对 ObjectClassesTrait 的看法, Scala 中的Sealed TraitCase Classes,我在下面写下我目前对它的理解:

我们创建 Object,当我们想在其中编写一些实用函数时,我们可以直接访问它,而无需像 Java 中的“静态”类那样使用“new”关键字。

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

当我们想编写与 Java 中的抽象类相同的代码时,我们创建了 Trait

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

我们创建Case类,当我们期望这个类将来可以用于模式匹配时,类似于Java中的instanceOf。

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

最佳答案

如果您用 OOP 的眼光来研究您所陈述的大部分事实,您或多或少是正确的。但我们对他们还有更多。

对象

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

object 可以看作是一个单例对象,因为您可以拥有一个 object 继承特定的 traitclass

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) = ???
}

关于类(class),你是对的。它们与 Java 概念非常接近。

特质

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

正如评论中所指出的,多个trait可以混合在一起。

如果 traits 是完全抽象的,也可以将其视为 Java interface,即所有方法都是抽象的,与 Java 一样。事实上,如果您的目标是与 Java 互操作,这就是声明 interface 的方式。

sealed trait 只是一种告诉编译器您不会有任何类或其他特征继承此特征的方式,除了同一文件中的那些。正如您在案例类中指出的那样,这用于模式匹配的目的,因此编译器能够通过警告判断模式匹配是否详尽。但也要注意 Scala 有 enum

案例类

为了模式匹配的目的,案例类可以与密封特征一起使用。但是 case class 更像是一个“value class”。 case 使编译器生成一堆样板代码,因此您不必这样做。

你有一个自动的“伴随对象”,所以你可以在没有 new 的情况下使用自动生成的 apply 函数实例化对象。

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

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)

关于java - Scala 中的类、对象、特征、密封特征,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29207230/

相关文章:

java - 加载包主类的正确方法是什么?

scala - 如何将 Akka Streams Merge 的输出通过管道传输到另一个 Flow?

javascript - Function.prototype.method 中的 return this 有什么作用?

java - 如何将下载的文件保存到另一台服务器

scala - 斯坦福解析器的标记化很慢?

c++ - 类的实例只允许 1 个方法,否则程序崩溃

Ruby 继承 - super 初始化得到错误数量的参数

java - 摩尔斯电码应用程序(JAVA Gui)

java - 有没有适用于 Android 的 GUI 工具?

java - 排除 Jhipster 并将 Spring Boot 从 1.4.0 升级到 2.0.3