2010-01-22 3 views
25

Классы классов в Scala являются стандартными классами, расширенными с помощью сопоставления с образцом, равными, ... (или я ошибаюсь?). Более того, они не требуют «нового» ключевого слова для их instanciation. Мне кажется, что их проще определить, чем обычные классы (или я снова ошибаюсь?).В каких случаях классы классов НЕ должны использоваться в Scala?

Существует множество веб-страниц, в которых говорится, где их следует использовать (в основном, о шаблоне matchin). Но где их следует избегать? Почему мы не используем их везде?

ответ

20

Есть много мест, где тематические классы не являются адекватными:

  • Когда кто-то хочет, чтобы скрыть структуру данных.
  • Как часть иерархии типов более чем двух или трех уровней.
  • Когда конструктор требует особых соображений.
  • Когда экстрактор требует особых соображений.
  • Если для равенства и хеш-кода требуются особые соображения.

Иногда эти требования появляются в конце конструкции и требуют преобразования класса case в нормальный класс. Так как преимущества класса case действительно не так уж велики - кроме нескольких особых случаев, которые они специально сделали для меня, моя собственная рекомендация - , а не, чтобы сделать что-нибудь класс случая, если для этого нет ясного использования.

Или, другими словами, не перестраивайте.

16

Наследование из классов корпуса проблематично. Предположим, что у вас есть код следующим образом:

case class Person(name: String) { } 

case class Homeowner(address: String,override val name: String) 
    extends Person(name) { } 

scala> Person("John") == Homeowner("1 Main St","John") 
res0: Boolean = true 

scala> Homeowner("1 Main St","John") == Person("John") 
res1: Boolean = false 

Возможно, это то, что вы хотите, но обычно вы хотите == B, если и только если б == а. К сожалению, компилятор не может разумно исправить это для вас автоматически.

Это становится еще хуже, потому что хэш-код из Person("John") не то же самое, как хэш-код в Homeowner("1 Main St","John"), так что теперь равно действует странно и хэш-код действует странно.

До тех пор, пока вы знаете, чего ожидать, наследование классов случаев может дать приемлемые результаты, но оно стало восприниматься как плохая форма (и, таким образом, оно устарело в 2.8).

+0

У вас есть ссылка на устаревшую функцию, которую вы упомянули, пожалуйста? –

+2

Поиск «наследование класса case» устарел »в Google, и три лучших хита обсудят его. Ухудшение уже в кодовой базе 2.8 - если вы загружаете ночную сборку, вы можете попробовать ее с помощью тривиального примера. –

0

Может возникнуть соблазн использовать классы case, потому что вы хотите бесплатно toString/equals/hashCode. Это может вызвать проблемы, поэтому не делайте этого.

Я бы хотел, чтобы была аннотация, позволяющая вам получить эти удобные вещи без создания класса case, но, возможно, это сложнее, чем кажется.

+2

«может вызвать проблемы». какие проблемы? –

1

Один недостаток, упомянутый в Programming in Scala, заключается в том, что из-за вещей, автоматически генерируемых для классов case, объекты становятся больше, чем для нормальных классов, поэтому, если важна эффективность памяти, вы можете использовать обычные классы.