Класс, объект, черта, запечатанная черта в Scala

Я из фона OOP и хочу очистить свое представление о Object, Classes, Trait, Sealed Trait и Case Classes в Scala, я пишу ниже, что я понимаю о это до сих пор:

Мы создаем Object, когда хотим закодировать некоторые функции утилиты внутри него, и мы можем получить к нему доступ напрямую, без использования "нового" ключевого слова, такого как "статические" классы в Java.

Мы создаем Classes, когда мы кодируем для глагола, означает объект и его поведение, инкапсулированное так же, как мы кодируем для классов в Java, и мы создаем его с помощью нового слова.

Мы создаем Trait, когда хотим кодировать те же, что и абстрактные классы в Java.

Мы создаем Sealed Trait, когда хотим добиться функциональности как одного и того же Enum в Java.

Мы создаем Case Classes, когда можем ожидать, что этот класс можно использовать для сопоставления шаблонов в будущем, аналогично instanceOf в Java.

Насколько я понимаю все это?

Ответ 1

Вы более или менее правы относительно большинства фактов, которые вы указали, если вы посмотрите на них глазами ООП. Но у нас их больше.

Объект

Объекты в Scala видны с точки зрения функционального программирования в качестве модулей. Они служат для объединения аналогичных функций, которые вы назвали "служебными функциями". Но они также имеют дополнительные значения.

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

Класс

Вы правы в занятиях. Они очень близки к понятию Java.

Тре

Один из способов просмотра trait в Scala - это abstract class. Но обратите внимание, что вы также можете иметь abstract class в Scala, с тем же поведением, что и в Java. Итак, какая разница?

Как указано в комментарии, несколько trait могут быть смешаны вместе.

Также trait можно рассматривать как Java interface, если он полностью абстрактный, то есть все методы абстрактны, как с Java. На самом деле, если вы нацеливаетесь на взаимодействие с Java, это способ объявить interface.

A sealed trait - это просто способ сообщить компилятору, что у вас не будет классов или других признаков, наследующих этот, кроме тех, которые находятся в одном файле. Это служит для сопоставления шаблонов, как вы отметили классы case, поэтому компилятор может определить, является ли соответствие шаблона исчерпывающим с предупреждением. Но также обратите внимание, что 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)