Надкласи та підкласи

Ми дізналися, що об'єкти успадковують властивості від об'єкта прототипу їх конструктора. Як вони можуть успадковувати характеристики ще й від класу 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 &&