我来自OOP
背景,并希望明确我对Object
,Classes
,Trait
,Sealed Trait
和Case Classes
的看法Scala
,我写下目前为止我对它的理解:
我们创建Object
,当我们想要在其中编写一些实用程序函数时,我们可以直接访问它,而不使用Java中的“new”关键字作为“静态”类。
我们创建Classes
,当我们编写动词时意味着一个对象,它的行为封装与我们为Java中的类编码相同,我们使用“new”关键字对其进行实例化。
当我们想要在Trait
中编写与抽象类相同的代码时,我们会创建Java
。
当我们想要在Java中实现与Enum相同的功能时,我们创建Sealed Trait
。
我们创建Case classes
时,我们可以预期此类可以在将来用于模式匹配,类似于Java中的instanceOf。
我的理解是否正确?
答案 0 :(得分:19)
如果你用OOP眼睛观察它们,你或多或少都对你所陈述的大部分事实都是正确的。但是我们还有更多的东西。
Scala中的对象可以从功能编程角度看作 modules 。它们的确用于聚合您称为“效用函数”的类似的kinded函数。但它们也有其他含义。
可以将object
视为单个对象,因为您可以拥有一个继承特定object
或trait
的{{1}}。
class
您还拥有伴侣对象的概念。这是一个具有与该类相关的模块函数的对象,您甚至可以从该类中引用该对象的trait Bird
object Duck extends Bird
成员。
private
你对课程是正确的。它们与Java概念非常接近。
在Scala中查看class Dog {
def eat(food: Food) = Dog.preferredFoods.contains(food)
}
object Dog {
private val preferredFoods = List(Ribeye, DogFood, Banana)
def walk(dog: Dog) = ???
}
的一种方法是trait
。但请注意,Scala中也可以有abstract class
,其行为与Java相同。那有什么区别?
正如评论中所指出的,可以将几个abstract class
混合在一起。
如果trait
完全是抽象的,那么trait
也可以被视为Java interface
,即所有方法都是抽象的,就像Java一样。实际上,如果您的目标是使用Java进行互操作,那就是声明interface
的方法。
sealed trait
只是一种告诉编译器你不会有任何类或其他特性继承这个特性的方法,除了同一个文件中的类。当你指出案例类时,这就是模式匹配的目的,因此编译器能够通过警告判断模式匹配是否详尽无遗。但另请注意,Scala有enum
。
案例类可以与sealed trait
一起用于模式匹配。但是case 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)