Рассмотрим следующий код:
case class Vector3(var x: Float, var y: Float, var z: Float)
{
def add(v: Vector3): Unit =
{
this.x += v.x
this.y += v.y
this.z += v.z
}
}
Как видите, case class
имеет изменяемое состояние. Крайне не рекомендуется делать это, и обычно я согласен и абсолютно придерживаюсь этого «правила», но вот и вся история.
Я использую Scala, чтобы написать небольшой 3D-игровой движок с нуля. Итак, сначала я подумал об использовании (гораздо более) функционального стиля, но потом слишком часто срабатывал сборщик мусора.
Подумайте об этом на мгновение: у меня есть десятки и десятки сущностей в тестовой игре. Все они имеют положение (Вектор3), ориентацию (Вектор3), масштаб (Вектор3) и множество Матриц. Если бы я собирался сделать эти классы (Vector3 и Matrix4) функциональными и сделать их неизменяемыми, я бы возвращал сотни новых объектов в каждом кадре, что приводило бы к огромной потере кадров в секунду, потому что, скажем прямо, у GC есть свое применение, но в игровой движок, а с OpenGL... не очень.
Раньше Vector3 был классом, но теперь это case-класс, потому что где-то в коде мне нужно для него сопоставление с образцом.
Итак, действительно ли это плохо использовать case-класс, который содержит изменяемое состояние?
Пожалуйста, не превращайте это в дискуссию на тему "Почему вы вообще используете Scala для такого проекта?" Я знаю, что могут быть лучшие альтернативы, но я не заинтересован в написании (еще одного) движка на C++, и я не слишком горю желанием погрузиться в Rust (пока).