Когда использовать фабрику сопутствующих объектов по сравнению с новым ключевым словом
Многие классы в стандартной библиотеке Scala используют apply()
их сопутствующий объект как фабрика. Это часто удобно, когда цепочки вызовов, такие как List(List(1))
, С другой стороны, все еще возможно создавать объекты непосредственно с new
(new HashMap[Int, Int]()
).
Это стандартная библиотека. Теперь, в моем собственном коде, какой подход лучше использовать: фабрика-компаньон или создание объектов с new
?
Есть ли соглашение о том, когда создавать фабрику сопутствующих объектов и когда делать с new
ключевое слово?
Каковы преимущества использования одного над другим?
2 ответа
В большинстве случаев я использую объект-компаньон apply
метод, потому что код выглядит менее загроможденным. Однако есть как минимум одно преимущество использования статической фабрики. Рассмотрим невообразимый тип MyInt
который просто оборачивает Int
:
class MyInt(val i: Int)
Я могу получить примеры MyInt
вызов конструктора, который будет создавать новый объект каждый раз, когда вызывается конструктор. Если моя программа сильно зависит от MyInt
это приводит к созданию множества экземпляров. Предполагая, что большинство MyInt
Я использую -1
, 0
, а также 1
, поскольку MyInt
неизменен, я могу использовать те же экземпляры:
class MyInt(val i: Int)
object MyInt {
val one = new MyInt(1)
val zero = new MyInt(0)
val minusOne = new MyInt(-1)
def apply(i: Int) = i match {
case -1 => minusOne
case 0 => zero
case 1 => one
case _ => new MyInt(i)
}
}
Поэтому, по крайней мере, для неизменяемых значений может быть техническое преимущество использования статической фабрики перед вызовом конструктора. Как следствие, если вы хотите выразить в коде, что создается новый экземпляр, то используйте new
ключевое слово. Лично я использую new
ключевое слово при создании объектов, а apply
-метод при создании ценностей, хотя я не знаю, существует ли официальное соглашение.
Я не знаю, что есть общая рекомендация одного подхода над другим, обычно это просто удобство, чтобы не печатать new
,
Однако бывают случаи, когда фабричный метод может быть лучше. Например, если в вашем классе есть поле String, которое должно быть в верхнем регистре, вы можете сделать стандартный конструктор закрытым, принудительно создавая экземпляр с помощью метода factory, который гарантирует, что поле всегда будет в верхнем регистре:
class A private[A] (s: String)
object A {
def apply(s: String): A = new A(s.toUpperCase)
}
Примечание: если ваш класс является классом case, есть пара других настроек, чтобы заставить его работать полностью - см. Здесь.