JavaScript. Подробное руководство, 6-е издание, стр. 125

<b>  return defineSubclass(this, constructor, methods, statics);</b>

<b>};</b>

Пример 9.12 демонстрирует, как определить подкласс «вручную», без использования функции def ineSubclass(). В этом примере определяется подкласс SingletonSet класса Set. Класс SingletonSet представляет специализированное множество, доступное только для чтения и состоящее из единственного постоянно элемента.

Пример 9.12. SingletonSet: простой подкласс множеств

<b>// Функция-конструктор</b>

<b>function SingletonSet(member) {</b>

<b>  this.member = member; // Сохранить единственный элемент множества</b>

<b>}</b>

<b>// Создает объект-прототип, наследующий объект-прототип класса Set.</b>

<b>SingletonSet.prototype = inherit(Set.prototype);</b>

<b>// Далее добавляются свойства в прототип.</b>

<b>// Эти свойства переопределяют одноименные свойства объекта</b>

<b>Set.prototype. extend(SingletonSet.prototype, {</b>

<b>  // Установить свойство constructor</b>

<b>  constructor: SingletonSet,</b>

<b>  // Данное множество доступно только для чтения: методы add() и remove()</b>

<b>  // возбуждают исключение</b>

<b>  add: function() { throw &quot;множество доступно только для чтения&quot;; },</b>

<b>  remove: function() { throw &quot;множество доступно только для чтения&quot;; },</b>

<b>  // Экземпляры SingletonSet всегда имеют размер, равный 1</b>

<b>  size: function() { return 1; },</b>

<b>  // Достаточно вызвать функцию один раз и передать ей единственный элемент,</b>

<b>  foreach: function(f, context) { f.call(context, this.member); },</b>

<b>  // Метод contains() стал проще: такая реализация пригодна только</b>

<b>  // для множества с единственным элементом</b>

<b>  contains: function(x) { return х === this.member; }</b>

<b>});</b>

Класс

<b>SingletonSet</b>
имеет очень простую реализацию, состоящую из пяти простых методов. Этот класс не только реализует пять основных методов класса
<b>Set</b>
, но и наследует от своего суперкласса такие методы, как
<b>toString(), toArray() и equals().</b>
Возможность наследования методов является одной из основных причин определения подклассов. Метод
<b>equals()</b>
класса
<b>Set</b>
(определен в разделе 9.6.4), например, может сравнивать любые экземпляры класса
<b>Set</b>
, имеющие методы
<b>size()</b>
и
<b>foreach(),</b>
с любыми экземплярами класса
<b>Set,</b>
имеющими методы
<b>size()</b>
и
<b>contains().</b>
Поскольку класс
<b>SingletonSet</b>
является подклассом класса
<b>Set</b>
, он автоматически наследует его метод
<b>equals()</b>
и не обязан иметь собственную реализацию этого метода. Безусловно, учитывая чрезвычайно упрощенную структуру множества, содержащего единственный элемент, можно было бы реализовать для класса
<b>SingletonSet </b>
более эффективную версию метода
<b>equals():</b>

<b>SingletonSet.prototype.equals = function(that) {</b>

<b>  return that instanceof Set &amp;&amp; that.size()==1 &amp;&amp; that.contains(this.member);</b>

<b>};</b>

Обратите внимание, что класс

<b>SingletonSet</b>
не просто заимствует список методов из класса
<b>Set</b>
: он динамически наследует методы класса
<b>Set</b>
. Если в
<b>Set.prototype</b>
добавить новый метод, он тут же станет доступен всем экземплярам классов
<b>Set</b>
и
<b>SingletonSet</b>
(в предположении, что класс
<b>SingletonSet </b>
не определяет собственный метод с таким же именем).

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

Класс

<b>SingletonSet</b>
из предыдущего раздела определяет совершенно новый тип множеств и полностью переопределяет основные методы, наследуемые от суперкласса. Однако часто при определении подкласса необходимо лишь расширить или немного изменить поведение методов суперкласса, а не заменить их полностью. В этом случае конструктор и методы подкласса могут вызывать конструктор и методы базового класса.

Пример 9.13 демонстрирует применение этого приема. Он определяет подкласс

<b>NonNullSet</b>
класса
<b>Set</b>
: тип множеств, которые не могут содержать элементы со значениями
<b>null</b>
и
<b>undefined</b>
. Чтобы исключить возможность включения в множество таких элементов, класс
<b>NonNullSet</b>
должен выполнить в методе
<b>add()</b>
проверку значений добавляемых элементов на равенство значениям
<b>null</b>
и
<b>undefined</b>
. Но при этом не требуется включать в класс полную реализацию метода
<b>add()</b>
- можно просто вызвать версию метода из суперкласса. Обратите также внимание, что конструктор
<b>NonNullSet()</b>
тоже не реализует все необходимые операции: он просто передает свои аргументы конструктору суперкласса (вызывая его как функцию, а не как конструктор), чтобы конструктор суперкласса мог инициализировать вновь созданный объект.