Java Scala中的类、对象、特征、密封特征

Java Scala中的类、对象、特征、密封特征,java,scala,oop,functional-programming,Java,Scala,Oop,Functional Programming,我来自OOP背景,想澄清我对Scala中的对象、类、特征、密封特征和案例类的看法,我将目前为止对它的理解写在下面: 我们创建对象,当我们想在其中编写一些实用程序函数时,我们可以直接访问它,而不需要使用“new”关键字,比如Java中的“Static”类 我们创建类,当我们为动词表示一个对象进行编码时,它的行为与我们在Java中为类编码时一样,我们使用“new”关键字对其进行实例化 当我们想在Java中编写与抽象类相同的代码时,我们创建了Trait 当我们想要实现Java中相同枚举的功能时,我们创

我来自
OOP
背景,想澄清我对
Scala
中的
对象
特征
密封特征
案例类
的看法,我将目前为止对它的理解写在下面:

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

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

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

当我们想要实现Java中相同枚举的功能时,我们创建了
Sealed Trait

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


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

如果你用面向对象的眼光审视这些事实,你所陈述的大部分事实或多或少是正确的。但我们对他们还有更多的要求

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

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

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中查看
特征的一种方法是将其作为
抽象类
。但请注意,Scala中也可以有一个
抽象类
,其行为与Java中相同。那么有什么区别呢

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

另外,如果是完全抽象的,
trait
s可以被看作是一个Java
接口,也就是说,所有的方法都像Java一样是抽象的。事实上,如果您的目标是与Java的互操作,那么这就是声明
接口的方法

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

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

您有一个自动的“伴生对象”,因此您可以使用自动生成的
apply
功能在不使用
new
的情况下实例化对象

您有自动的
hashCode
等于
toString
复制
实现。对于所有构造函数的参数,都有自动
val
s

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)

仅评论“Trait”:由于您的类可以继承多个Trait(mix-ins),我不会将其与Java抽象类进行比较。您是说,我们可以在类中扩展多个Trait,但Java限制我们一次只扩展一个类?。如果是的话,还有其他区别吗?是的,你可以随心所欲地扩展你的特性。