Дэвид Флэнаган - JavaScript. Подробное руководство, 6-е издание
- Название:JavaScript. Подробное руководство, 6-е издание
- Автор:
- Жанр:
- Издательство:Символ-Плюс
- Год:2012
- Город:СПб
- ISBN:978-5-93286-215-5
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Дэвид Флэнаган - JavaScript. Подробное руководство, 6-е издание краткое содержание
Эта книга - одновременно и руководство программиста, и полноценный справочник по базовому языку JavaScript и клиентским прикладным интерфейсам, предоставляемым веб-броузерами.
JavaScript. Подробное руководство, 6-е издание - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
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).
9.7. Подклассы
В объектно-ориентированном программировании класс В может расширять, или наследовать, другой класс А. Класс А в этом случае называется суперклассом, а класс В - подклассом. Экземпляры класса В наследуют все методы экземпляров класса А. Класс В может определять собственные методы экземпляров, некоторые из которых могут переопределять методы класса А с теми же именами. Если метод класса В переопределяет метод класса А, переопределяющий метод класса В может вызывать переопределенный метод класса А: этот прием называется вызовом метода базового класса. Аналогично конструктор В() подкласса может вызывать конструктор А() суперкласса. Это называется вызовом конструктора базового класса. Подклассы сами могут наследоваться другими подклассами и, работая над созданием иерархии классов, иногда бывает полезно определять абстрактные классы. Абстрактный класс - это класс, в котором объявляется один или более методов без реализации. Реализация таких абстрактных методов возлагается на конкретные подклассы абстрактного класса.
Ключом к созданию подклассов в языке JavaScript является корректная инициализация объекта-прототипа. Если класс В расширяет класс А, то объект В.prototype должен наследовать A.prototype
. В этом случае экземпляры класса В будут наследовать свойства от объекта В.prototype
, который в свою очередь наследует свойства от A.prototype
. В этом разделе демонстрируются все представленные выше термины, связанные с подклассами, а также рассматривается прием, альтернативный наследованию, который называется композицией.
Используя в качестве основы класс Set
из примера 9.6, этот раздел продемонстрирует, как определять подклассы, как вызывать конструкторы базовых классов и переопределенные методы, как вместо наследования использовать прием композиции и, наконец, как отделять интерфейсы от реализации с помощью абстрактных классов. Этот раздел завершает расширенный пример, в котором определяется иерархия классов Set
. Следует отметить, что первые примеры в этом разделе служат цели продемонстрировать основные приемы использования механизма наследования, и некоторые из них имеют существенные недостатки, которые будут обсуждаться далее в этом же разделе.
9.7.1. Определение подкласса
В языке JavaScript объекты наследуют свойства (обычно методы) от объекта-прототипа своего класса. Если объект O
является экземпляром класса В
, а класс В
является подклассом класса А
, то объект O
также наследует свойства класса А
. Добиться этого можно за счет наследования объектом-прототипом класса В
свойств объекта-прототипа класса А
, как показано ниже, с использованием функции inherit()
(пример 6.1):
В.prototype = inherit(A.prototype); // Подкласс наследует суперкласс
В.prototype.constructor = В; // Переопределить унаследованное св. constructor
Эти две строки являются ключом к созданию подклассов в JavaScript. Без них объект-прототип будет обычным объектом - объектом, наследующим свойства от Object.prototype
, - а это означает, что класс будет подклассом класса Object
, подобно всем остальным классам. Если добавить эти две строки в функцию defineClass()
(раздел 9.3), ее можно будет преобразовать в функцию defineSubclass()
и в метод Function.prototype.extend(),
как показано в примере 9.11.
Пример 9.11. Вспомогательные инструменты определения подклассов
// Простая функция для создания простых подклассов
Интервал:
Закладка: