Когда использовать класс case или обычный класс
У меня есть недоразумение, в каких случаях я должен использовать класс case или обычный класс, следуя передовым методам. Я уже читал о различиях обоих классов, но не могу представить себе реальные примеры, в которых рекомендуется использовать случай или обычный класс.
Может ли кто-нибудь показать мне реальные примеры с объяснением, почему это рекомендуется для этого, а не иначе?
Ответы
Ответ 1
Если вы собираетесь писать чисто функциональный код с неизменяемыми объектами, лучше избегать использования обычных классов.
Основная идея функциональной парадигмы - разделение структур данных и операций над ними.
Классы классов представляют собой представление структуры данных с необходимыми методами. Функции на данных должны быть описаны в разных объектах программного обеспечения (например, чертах, объектах).
Регулярные классы, напротив, связывают данные и операции, чтобы обеспечить изменчивость. Этот подход ближе к объектно-ориентированной парадигме.
В результате не используйте классы Case, если:
- Ваш класс несет изменчивое состояние.
- В ваш класс входит некоторая логика.
- Ваш класс не является представлением данных, и вам не требуется структурное равенство.
Однако в этих случаях вы должны действительно думать о стиле своего кода, потому что он, вероятно, недостаточно функциональен.
Ответ 2
- Когда ваш класс переносит переменное состояние, не используйте классы case.
- Если вы хотите структурное равенство, используйте класс case, так как он дает вам правильные
hashCode
и equals
. Например, вы хотите использовать их как ключи в Set
или Map
Вот еще одно личное предпочтение:
- Когда вы просто хотите использовать автоматические геттеры, а вы помещаете экземпляры в
Set
или Map
, но у вас только один экземпляр и не требуется структурное равенство, предпочитайте class Foo(val i: Int)
над case class Foo(i: Int)
, потому что вы не имеют более дорогих проверок равенства.
Если 1. и 2. collide, вы можете реализовать определенные функции класса case вручную. Например, предоставите метод apply
сопутствующей программы или экстрактор соответствия шаблону для изменяемого класса, отличного от случая.
Ответ 3
Класс case дает вам "бесплатные" (т.е. вам не нужно писать) реализации equals
, hashcode
и toString
, а также apply
и unapply
в сопутствующем объекте,
В принципе, вы можете рассматривать класс case как named tuple, поля которого также называются.
Для чего-нибудь еще, вам, вероятно, лучше использовать обычный класс.
Ответ 4
Классы классов являются нормальными классами с синтаксическим сахаром. Таким образом, нет большой разницы, вы можете делать все с классом case, который вы можете сделать с классом, и наоборот.
Классы классов просто сэкономит вам много кода плиты котла для записи.
Идеальная подгонка, как следует из названия, - это использование классов case в сопоставлении шаблонов с case
.
case class MyCase(name: String, age: Int)
data : List[MyCase] = ...
data foreach {
case MyCase(_, age) if age > 21 => println("old enough")
case MyCase("fred", _ ) => println("Got you")
case _ => ...
}
Ответ 5
Нормальные классы - это классы как классы в Java. Он может содержать как состояние, так и функциональность.
Классы классов похожи на данные POJO в Java. классы, которые содержат состояние, которое может использоваться функциями (обычно в других классах).
Когда вы внедряете данные POJO в Java, вы должны установить переменную, которую она удерживает, добавить для них getter и setter, реализовать hashcode и equals и, возможно, реализовать toString.
Обычно это не так уж плохо, поскольку после определения переменных среда IDE может генерировать все для вас, но если вы меняете/добавляете переменные, вам следует помнить о том, чтобы обновить все методы.
в случае классов вы определяете переменные (или лучшие значения), а компилятор генерирует все методы для вас. Таким образом, вы получаете оба, без шаблонов и обновленных функций.
Для классов case компилятор также генерирует больше функциональных возможностей, которых вы не можете и не можете иметь в Java, функции копирования и применять/не использовать в объекте compaion.
Ответ 6
классы case являются центрами данных.
Мы получаем следующие преимущества, используя класс case над регулярными классами.
(1) Значение эквивалентности: это означает, что два случая могут сравниваться с значениями внутри них.
scala> case class Time(hours: Int = 0, mins: Int = 0)
defined class Time
scala> val time1 = Time(12, 13)
time1: Time = Time(12,13)
scala> val time2 = Time(11, 12)
time2: Time = Time(11,12)
scala> time1 == time2
res6: Boolean = false
scala> val time3 = Time(10, 11)
time3: Time = Time(10,11)
scala> time1 == time2
res7: Boolean = false
Но другие операторы сравнения ( > , >= <, и т.д.) не определены.
(2) Неизменяемые поля: потокобезопасные
(3) Автоматическое создание поля: часы и минуты являются неизменяемыми полями, автоматически создаваемыми Scala.
scala> time1.hours
res9: Int = 12
классы case также используются при разборе искровых строк DataFrame, и преимущество состоит в том, что к столбцам DataFrame можно получить имя поля класса case.