我来自 OOP
背景,想澄清我对 Object
、Classes
、Trait
的看法, Scala
中的Sealed Trait
和Case Classes
,我在下面写下我目前对它的理解:
我们创建 Object
,当我们想在其中编写一些实用函数时,我们可以直接访问它,而无需像 Java 中的“静态”类那样使用“new”关键字。
我们创建类
,当我们为动词编码时表示一个对象,它的行为封装与我们在 Java 中为类编码相同,我们使用“new”关键字实例化它。
当我们想编写与 Java
中的抽象类相同的代码时,我们创建了 Trait
。
当我们想在 Java 中实现与 Enum 相同的功能时,我们创建了Sealed Trait
。
我们创建Case类
,当我们期望这个类将来可以用于模式匹配时,类似于Java中的instanceOf。
我对这些的理解是否正确?
最佳答案
如果您用 OOP 的眼光来研究您所陈述的大部分事实,您或多或少是正确的。但我们对他们还有更多。
对象
从函数式编程的角度来看,Scala 中的对象可以看作是模块。它们确实用于聚合您称为“实用程序函数”的相似函数。但它们还有其他含义。
object
可以看作是一个单例对象,因为您可以拥有一个 object
继承特定的 trait
或 class
。
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
可以混合在一起。
如果 trait
s 是完全抽象的,也可以将其视为 Java interface
,即所有方法都是抽象的,与 Java 一样。事实上,如果您的目标是与 Java 互操作,这就是声明 interface
的方式。
sealed trait
只是一种告诉编译器您不会有任何类或其他特征继承此特征的方式,除了同一文件中的那些。正如您在案例类中指出的那样,这用于模式匹配的目的,因此编译器能够通过警告判断模式匹配是否详尽。但也要注意 Scala 有 enum
。
案例类
为了模式匹配的目的,案例类可以与密封特征
一起使用。但是 case class
更像是一个“value class”。 case
使编译器生成一堆样板代码,因此您不必这样做。
你有一个自动的“伴随对象”,所以你可以在没有 new
的情况下使用自动生成的 apply
函数实例化对象。
您有自动的hashCode
、equals
、toString
和copy
实现。并且所有构造函数的参数都有自动 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/