Интернет, компьютеры, софт и прочий Hi-Tech

Подписаться через RSS2Email.ru

ООП в JavaScript

Создаем подкласс

Допустим, нам понадобился объект, похожий на Person, но с дополнительной информацией о человек, как о служащем. Давайте определим подкласс для Person:

KevLinDev.extend = function(subClass, baseClass) {
   function inheritance() {}
   inheritance.prototype = baseClass.prototype;

   subClass.prototype = new inheritance();
   subClass.prototype.constructor = subClass;
   subClass.baseConstructor = baseClass;
   subClass.superClass = baseClass.prototype;
}

function Employee(first, last, id) {
    // здесь инициализируем свойства
}

KevLinDev.extend(Employee, Person);

Сначала мы создаем удобную функцию для задания нашей цепочки наследования. Нам необходимо сделать свойство subClass.prototype эквивалентным свойству baseClass.prototype. Помните, что при вызове "new" свойство "prototype" конструктора копируется в новый скрытый прототип объекта. Приведенная функция - это хак цепочки наследования. Нам нельзя обоим свойствам subClass.prototype и baseClass.prototype присвоить один и тот же объект прототипа. Иначе каждый метод, добавляемый в один класс, будет добавляться и в другой класс. Вместе с тем, если мы добавляем метод в базовый класс, он должен будет "унаследоваться" подклассом. То есть мы должны так рассоединить оба прототипа, чтобы разрешить subClass'у ссылаться на baseClass. Приходится опять спасать цепочку прототипов.

Мы начали с определения вспомогательной функции по имени "inheritance". Затем мы устанавливаем ее прототип в прототип baseClass'а. Экземпляр "inheritance", полученный с помощью "new", будет иметь скрытый прототип, ссылающийся на общедоступный прототип базового класса. Мы создаем новый экземпляр "inheritance" и присваиваем его прототипу subClass'а. Теперь, каждый раз, когда мы будем создавать новый экземпляр subClass'а, скрытый прототип этого экземпляра будет ссылаться на экземпляр "inheritance". А скрытый прототип "inheritance" будет ссылаться на общедоступный прототип базового класса. Значит, изменения baseClass.prototype будут распространяться на экземпляры подклассов через "inheritance", а когда мы будем создавать новые свойства подкласса, мы будем работать только с прототипом подкласса (subClass.prototype) не трогая прототип базового класса.

В JavaScript, когда вы создаете новый объект, его локальное свойство "constructor" определяется как указатель на функцию (конструктор), которая была вызвана для создания данного экземпляра. Я часто пользуюсь этим и сравниваю свойство "constructor" объекта с нужной функцией для определения "типа" данного объекта. В результате вызова "new inheritance()" указатель subClass.prototype.constructor начинает ссылаться на функцию "inheritance" и это портило мои тесты. Я пофиксил это обновлением свойства "constructor" на нужный мне конструктор subClass.

Последние две строки в коде функции "extend" используются как удобные соглашения для вызова конструктора и методов предка. Это будет продемонстрировано в следующем разделе.

Вызываем конструктор базового класса

Мы создали наш новый подкласс и теперь хотим чтобы при вызове "new" инициализировались его свойства. При этом желательно было бы не повторять в нашем подклассе Employee код базового класса Person. Нам нужно сделать так, чтобы параметры "first" и "last" обрабатывались конструктором Person, а параметр "id" - конструктором Employee. Следующий код показывает, как этого добиться:

function Employee(first, last, id) {
    Employee.baseConstructor.call(this, first, last);
    this.id = id;
}

Конечно, это выглядит несколько громоздко, но мы просто вызываем суперконструктор с помощью "call". Конструктор базового класса будет вызван так, как будто он является методом первого параметра функции "call", т.е. "this". Остальные параметры будут переданы в вызываемую функцию. Итак, в нашем случае конструктор базового класса Person обработает "first" и "last", а конструктор Employee обработает "id".

Читайте далее:


Кевин Линдсей (Kevin Lindsey), 2006

Перевод Д. Скоробогатова (20.10.2009).

Биржа долевых инвестиций SIMEX.

Последнее редактирование: 2010-01-05 15:43:41

Метки материала: ООП, JS, производный класс, конструктор, экземпляр класса, указатель, указатели, передача по ссылке, определение функции, инкапсуляция, базовые классы, алгоритм, this, new, явная инициализация, constructor, метод, class, функция, члены класса, script

Оставьте, пожалуйста, свой комментарий к публикации

Представиться как     Антибот:
   

Просьба не постить мусор. Если вы хотите потестить xBB, воспользуйтесь кнопкой предварительного просмотра на панели инструментов xBBEditor-а.


© 2007-2017, Дмитрий Скоробогатов.
Разрешается воспроизводить, распространять и/или изменять материалы сайта
в соответствии с условиями GNU Free Documentation License,
версии 1.2 или любой более поздней версии, опубликованной FSF,
если только иное не указано в самих материалах.