【问题标题】:Class, Object, Trait, Sealed Trait in ScalaScala 中的类、对象、特征、密封特征
【发布时间】:2015-05-26 06:21:21
【问题描述】:

我来自OOP 背景,并且想澄清我对ObjectClassesTraitSealed TraitCase Classes 的想法Scala,我在下面写下我所了解的到目前为止:

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

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

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

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

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

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

【问题讨论】:

  • 仅评论“Trait”:由于您的类可以继承多个特征(混合),因此我不会将其与 Java 抽象类进行比较。
  • 您是说,我们可以在类中扩展多个 Trait,但 Java 限制我们一次只能扩展一个类?如果有,还有其他区别吗?
  • 是的,您可以根据需要扩展任意数量的特征。

标签: java scala oop functional-programming


【解决方案1】:

如果您以 OOP 的眼光审视您所陈述的大多数事实,您或多或少是正确的。但我们对他们还有更多。

对象

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

object 可以被视为一个单例对象,因为您可以拥有一个继承特定 traitclassobject

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 中查看trait 的一种方法是使用abstract class。但请注意,您也可以在 Scala 中使用 abstract class,其行为与在 Java 中相同。那么有什么区别呢?

正如评论中指出的,几个traits 可以混在一起。

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

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

案例分类

案例类可以与sealed trait 一起用于模式匹配。但是case class 更像是一个“价值类”。 case 使编译器生成一堆样板代码,因此您不必这样做。

您有一个自动的“伴随对象”,因此您可以在没有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)

【讨论】:

    猜你喜欢
    • 2017-09-08
    • 1970-01-01
    • 2017-10-25
    • 1970-01-01
    • 1970-01-01
    • 2015-09-17
    • 1970-01-01
    • 1970-01-01
    • 2018-12-18
    相关资源
    最近更新 更多