Книга: JavaScript. Подробное руководство, 6-е издание
9.6.7. Перегрузка конструкторов и фабричные методы
9.6.7. Перегрузка конструкторов и фабричные методы
Иногда бывает необходимо реализовать возможность инициализации объектов несколькими способами. Например, можно было бы предусмотреть возможность инициализации объекта Complex
значениями радиуса и угла (полярные координаты) вместо вещественной и мнимой составляющих. Или создавать объекты множеств Set
, членами которых являются элементы массива, а не аргументы конструктора.
Один из способов реализовать такую возможность заключается в создании перегруженных версий конструктора и выполнении в них различных способов инициализации в зависимости от передаваемых аргументов. Ниже приводится пример перегруженной версии конструктора Set
:
function Set() {
this.values = {}; // Свойство для хранения множества
this.n =0; // Количество значений в множестве
// Если конструктору передается единственный объект, подобный массиву,
// он добавляет элементы массива в множество.
// В противном случае в множество добавляются все аргументы
if (arguments.length == 1 && isArraylike(arguments[0]))
this.add.apply(this, arguments[0]);
else
if (arguments.length > 0)
this.add.apply(this, arguments);
}
Такое определение конструктора Set()
позволяет явно перечислять элементы множества в вызове конструктора или передавать ему массив элементов множества. К сожалению, этот конструктор имеет одну неоднозначность: его нельзя использовать для создания множества, содержащего единственный элемент-массив. (Для этого потребуется создать пустое множество, а затем явно вызвать метод add()
.)
В случае с комплексными числами реализовать перегруженную версию конструктора, которая инициализирует объект полярными координатами, вообще невозможно. Оба представления комплексных чисел состоят из двух вещественных чисел. Если не добавить в конструктор третий аргумент, он не сможет по своим аргументам определить, какое представление следует использовать. Однако вместо этого можно написать фабричный метод - метод класса, возвращающий экземпляр класса. Ниже приводится фабричный метод, возвращающий объект Complex
, инициализированный полярными координатами:
Complex.polar = function(r, theta) {
return new Complex(r*Math.cos(theta), r*Math.sin(theta));
};
А так можно реализовать фабричный метод для инициализации объекта Set
массивом:
Set.fromArray = function(a) {
s = new Set(); // Создать пустое множество
s.add.apply(s, a); // Передать элементы массива методу add
return s; // Вернуть новое множество
};
Привлекательность фабричных методов заключается в том, что им можно дать любые имена, а методы с разными именами могут выполнять разные виды инициализации. Поскольку конструкторы играют роль имен классов, обычно в классах определяется единственный конструктор. Однако это не является непреложным правилом. В языке JavaScript допускается определять несколько функций-конструкторов, использующих общий объект-прототип, и в этом случае объекты, созданные разными конструкторами одного класса, будут иметь один и тот же тип. Данный прием не рекомендуется к использованию, тем не менее ниже приводится вспомогательный конструктор такого рода:
// Вспомогательный конструктор для класса Set.
function SetFromArray(a) {
// Инициализировать новый объект вызовом конструктора Set() как функции,
// передав ей элементы массива в виде отдельных аргументов.
Set.apply(this, а);
}
// Установить прототип, чтобы функция SetFromArray создавала экземпляры Set
SetFromArray.prototype = Set.prototype;
var s = new SetFromArray([1,2,3]);
s instanceof Set // => true
В ECMAScript 5 функции имеют метод bind(),
особенности которого позволяют создавать подобные вспомогательные конструкторы (раздел 8.7.4).
- Перегрузка методов с несколькими параметрами типа
- Перегрузка конструкторов
- ОО-разработка и перегрузка
- Глава 3. Информационная перегрузка
- Семантическая перегрузка (предварительное представление)
- ГЛАВА 9 Перегрузка операторов
- Перегрузка и универсальность
- Синтаксическая перегрузка
- Процедуры создания и перегрузка
- Наследование конструкторов
- Перегрузка операций проверки на тождественность
- Перегрузка имен подпрограмм