2015-08-28 7 views
9

Многие классы в стандартной библиотеке Scala используют apply() своего компаньона в качестве фабрики. Это часто удобно при цепочке звонков, например, List(List(1)). С другой стороны, по-прежнему можно создавать объекты непосредственно с new (new HashMap[Int, Int]()).Когда использовать объект компаньона фабрики против нового ключевого слова

Это стандартная библиотека. Теперь, в моем собственном коде, какой подход лучше использовать: фабрика компаньона или создание объектов с new?

Существует ли какое-либо соглашение о том, когда следует создавать фабрику компаньонов и когда нужно использовать ключевое слово new?

В чем преимущества использования одного над другим?

+4

Потому что использование 'new' похоже на верхнюю шляпу или подтяжки. Он стильный для определенного стиля, но не очень современный. Сопутствующая фабрика - это пара повседневных джинсов. –

ответ

3

В большинстве случаев я использую метод компаньона 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 - при создании значений, хотя я не знаю, существует ли официальное соглашение.

+1

Мне нравится идея с кешированием ценности. Извлеченный урок состоит в том, что вы можете легко изменить реализацию apply(), чтобы делать все, что хотите, но когда вы используете 'new', вы всегда должны иметь новый экземпляр. – Mifeet

3

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

Есть случаи, когда опция заводского метода может быть лучше. Например, если ваш класс имеет поле Строки, которая должна быть в верхнем регистре, вы можете сделать стандартный конструктор приватным, заставляя экземпляр через фабричный метод, который обеспечивает поле всегда в верхнем регистре:

class A private[A] (s: String) 

object A { 
    def apply(s: String): A = new A(s.toUpperCase) 
} 

Примечания: если ваш класс класс корпуса, есть несколько других ухищрений, чтобы заставить его работать полностью - см. here.

+1

Как деталь, 'private [A]' приводит к публичному ctor. Более обычное, просто для 'private', поскольку оно означает то же самое для Scala, но имеет частный ctor для Java. –

+0

У меня нет такого опыта работы с Scala, но не надо ли вам докучать дополнительный компаньон для каждого объекта? – Mifeet

+0

классы @Mifeet Case предоставляют (обычно) подходящий сопутствующий объект бесплатно, поэтому, как правило, он не беспокоит вообще. – Shadowlands