Вход/Регистрация
JavaScript. Подробное руководство, 6-е издание
вернуться

Флэнаган Дэвид

Шрифт:

function FilteredSet(set, filter) { // Конструктор

this.set = set; this.filter = filter;

},

{ // Методы экземпляров

add: function {

// Если фильтр был указан, применить его

if (this.filter) {

for(var і = 0; і < arguments.length; i++) {

var v = arguments[i];

if (!this.filter(v))

throw new Error("FilteredSet: значение " + v + " отвергнуто фильтром");

}

}

// Затем вызвать метод add объекта

this.set.add this.set.add.apply(this.set, arguments);

return this;

},

// Остальные методы просто вызывают соответствующие

// методы объекта this.set и ничего более,

remove: function {

this.set.remove.apply(this.set, arguments);

return this;

}.

contains: function(v) {
return this.set.contains(v);},

size: function { return this.set.size; },

foreach: function(f,c) { this.set.foreach(f.c); }

}

)

Одно из преимуществ применения приема композиции в данном случае заключается в том, что требуется определить только один подкласс

FilteredSe
t. Экземпляры этого класса могут накладывать ограничения на элементы любого другого эк» земпляра множества. Например, вместо класса
NonNullSet
, представленного выше, реализовать подобные ограничения можно было бы так:

var s = new FilteredSet(new Set, function(x) { return x !== null; });

Можно даже наложить еще один фильтр на фильтрованное множество:

var t = new FilteredSet(s, { function(x) { return !(x instanceof Set); });

9.7.4. Иерархии классов и абстрактные классы

В предыдущем разделе было предложено «предпочесть композицию наследованию». Но для иллюстрации этого принципа мы создали подкласс класса

Set
. Сделано это было для того, чтобы получившийся подкласс был
instanceof Set
и наследовал полезные методы класса
Set
, такие как
toString
и
equals.
Это достаточно уважительные причины, но, тем не менее, было бы неплохо иметь возможность использовать прием композиции без необходимости наследовать некоторую определенную реализацию множества, такую как класс
Set
. Аналогичный подход можно было бы использовать и при создании класса
SingletonSet
(пример 9.12) -этот класс был определен как подкласс класса
Set
, чтобы унаследовать вспомогательные методы, но его реализация существенно отличается от реализации суперкласса. Класс
SingletonSet
– это не специализированная версия класса
Set
, а совершенно иной тип множеств. В иерархии классов
SingletonSet
должен был бы находиться на одном уровне с классом
Set
, а не быть его потомком.

Решение этой проблемы в классических объектно-ориентированных языках, а также в языке

JavaScript
заключается в том, чтобы отделить интерфейс от реализации. Представьте, что мы определили класс
AbstractSet
, реализующий вспомогательные методы, такие как
toString,
в котором отсутствуют реализации базовых методов, таких как
foreach.
Тогда все наши реализации множеств -
Set, SingletonSet
и
FilteredSet
– могли бы наследовать класс
AbstractSet
. При этом классы
FilteredSet
и
SingletonSet
больше не наследовали бы ненужные им реализации.

Пример 9.16 развивает этот подход еще дальше и определяет иерархию абстрактных классов множеств. Класс

AbstractSet
определяет только один абстрактный метод,
contains.
Любой класс, который претендует на роль множества, должен будет определить хотя бы один этот метод. Далее в примере определяется класс
AbstractEnumerableSet
, наследующий класс
AbstractSet
. Этот класс определяет абстрактные методы
size
and
foreach
и реализует конкретные вспомогательные методы (
toString, toArray, equals
и т.д.).
AbstractEnumerableSet
не определяет методы
add
или
remove
и представляет класс множеств, доступных только для чтения. Класс
SingletonSet
может быть реализован как конкретный подкласс. Наконец, в примере определяется класс
AbstractWritableSet
, наследующий
AbstractEnumerableSet
. Этот последний абстрактный класс определяет абстрактные методы
add
и
remove
и реализует конкретные методы, такие как
union
и
intersection,
использующие их. Класс
AbstractWritableSet
отлично подходит на роль суперкласса для наших классов
Set
и
FilteredSet
. Однако они не были добавлены в пример, а вместо них была включена новая конкретная реализация с именем
ArraySet
.

Пример 9.16 довольно объемен, но он заслуживает детального изучения. Обратите внимание, что для простоты создания подклассов в нем используется функция

Function.prototype.extend.

Пример 9.16. Иерархия абстрактных и конкретных классов множеств

// Вспомогательная функция, которая может использоваться для определения

// любого абстрактного метода

  • Читать дальше
  • 1
  • ...
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: