Надкласи та підкласи
Ми дізналися, що об'єкти успадковують властивості від об'єкта прототипу їх конструктора. Як вони можуть успадковувати характеристики ще й від класу Object? Згадайте, що объект_прототип сам є об'єкт; він створюється за допомогою конст_
1 Але при такому визначенні досить «дивну» семантику знаходять оператори відносини. -Прим. наук. ред.
| 9.5. Надкласи та підкласи |
руктора Object(). Це означає, що объект_прототип успадковує властивості від Ob_ject.prototype! Тому об'єкт класу Complex успадковує властивості від об'єкта Com_plex.prototype, який у свою чергу успадковує властивості від Object.prototype. Коли виконується пошук певної властивості в об'єкті Complex, спочатку виконується пошук у самому об'єкті. Якщо властивість не знайдено, пошук продовжується в об'єкті Complex.prototype. І нарешті, якщо властивість не знайдено і в цьому об'єкті, виконується пошук в об'єкті Object.prototype.
Зверніть увагу: оскільки в об'єкті_прототипі Complex пошук відбувається раніше, ніж в об'єкті_прототипі Object, властивості об'єкта Complex.prototype приховують будь-які властивості з тим самим ім'ям з Object.prototype. Так, у класі, показаному в прикладі 9.2, ми визначили в об'єкті Complex.prototype метод toString(). Object.prototype також визначає метод із цим ім'ям, але об'єкти Complex ніколи не побачать його, оскільки визначення toString() у Complex.proto_ type буде знайдено раніше.
Всі класи, які ми показали в цьому розділі, є безпосередніми підкласами класу Object. Це притаманно програмування на Java_ Script; зазвичай у створенні більш складної ієрархії класів немає ніякої необхідності. Однак, коли це потрібно, можна створити підклас будь-якого іншого класу. Припустимо, що ми хочемо створитипідклас класу Rectangle, щоб додати до нього властивості та методи, пов'язані з координатами прямокутника. Для цього ми просто повинні бути впевнені, що об'єкт_прототип нового класу сам є екземпляром Rectangle і тому успадковує всі властивості Rectang le.prototype. Приклад 9.3 повторює визначення простого класу Rectanle і потім розширює це визначення за рахунок створення нового класу PositionedRectangle.
// Визначення простого класу прямокутників.
// Цей клас має ширину та висоту і може обчислювати свою площу function Rectangle(w, h)
// Далі йде визначення підкласу
Function PositionedRectangle(x, y, w, h)
// Насамперед необхідно викликати конструктор надкласу
// для ініціалізації властивостей width і height нового об'єкта.
// Тут використовується метод call, щоб конструктор був викликаний
// як метод об'єкта, що ініціалізується.
// Це називається виклик конструктора з ланцюжка. Rectangle.call(this, w, h);
//Далі зберігаються координати верхнього лівого кута прямокутника this.x = x;
// Якщо ми будемо використовувати об'єкт_прототип за замовчуванням,
// який створюється щодо конструктора PositionedRectangle(),
// Було б створено підклас класу Object.
184 Розділ 9. Класи, конструктори та прототипи
// Щоб створити підклас класу Rectangle, необхідно створити об'єкт_прототип. PositionedRectangle.prototype = новий Rectangle();
// Ми створили объект_прототип з успадкування, але ми збираємося
// успадковувати властивості width і height, якими мають усі об'єкти
// класу Rectangle, тому видалимо їх із прототипу.
delete PositionedRectangle.prototype.width; deletePositionedRectangle.prototype.height;
// Оскільки об'єкт_прототип було створено за допомогою конструктора
// Rectangle(), властивість конструктора в ньому посилається на цей
// Конструктор. Але нам потрібно, щоб об'єкти PositionedRectangle
// посилалися інший конструктор, тому далі виконується
// привласнення нового значення властивості constructor PositionedRectangle.prototype.constructor = PositionedRectangle;
// Тепер у нас є правильно налаштований прототип для нашого
/ / Підкласу, можна приступати до додавання методів екземплярів. PositionedRectangle.prototype.contains = function(x,y)
return (x > this.x & x this.y && y 1 Може також з'явитися бажання видалити будь-які властивості, які створюються конструктором надкласу в объекте_прототипе, оскільки дуже важливо, щоб властивості объекта_прототипа успадковувалися зйого прототипу.
Маючи таке визначення класу PositionedRectangle, його можна використовувати у своїх програмах приблизно так:
| var r = new | Положенняректанглі(2,2,2,2); | |||
| print(r.contains(3,3)); // | Викликається | метод екземпляра | ||
| print(r.area( )); | // | Викликається | успадкований метод екземпляра | |
| // Робота | з | полями | екземпляра | класу: |
| print(r.x | + | "," + | r.y + "," | + r.width + "," + r.height); |
// Наш об'єкт може розглядатися як екземпляр усіх 3 класів
| 9.5. Надкласи та підкласи |
print(r instanceof PositionedRectangle && r instanceof Rectangle &&