Страницы

Поиск по вопросам

суббота, 6 июля 2019 г.

Виртуальный метод при композиции

Объект класса с двумя методами getOuter и getInner оборачивается другим классом, имеющим такой же интерфейс, но используется не наследование а композиция, т. е. объект вкладывается внутрь другого и они должны иметь независимые поля.
Известно, что из метода getOuter ровно один раз вызывается метод getInner. Надо сделать так, чтобы вызывался getInner не оборачиваемого объекта, а оборачивающего. В качестве прокси используется класс Wrapper, от которого наследуются обрачивающие классы. Что надо в него дописать, чтобы работало соответствующим образом?
Желаемый вывод после дописывания врэппера:
outer c b a (<[Bb][Aa]>)
class A { constructor() { this.x = 'A'; this.a = 'a'; } getOuter() { console.log('outer'); return `(${this.getInner()})`; } getInner() { console.log('a'); return this.x + this.a; } } var a = new A class Wrapper { constructor(original) { this.original = original } getOuter() { return this.original.getOuter(); } getInner() { return this.original.getInner(); } } class B extends Wrapper { constructor(original) { super(original); this.x = 'B'; this.b = 'b'; } getInner() { console.log('b'); return `[${this.x}${this.b}][${super.getInner()}]`; } } var b = new B(a); class C extends Wrapper { constructor(original) { super(original); this.x = 'C'; this.c = 'c'; } getInner() { console.log('c'); return `<${this.x}${this.c}><${super.getInner()}>`; } } var c = new C(b); console.log(c.getOuter());


Ответ

Ура, кажется получилось!
Надо в getOuter в оборачиваемый инстанс сохранить забинженный метод getInner текущего класса, в когда тот вызовет super.getInner, то эту ссылку затереть и продолжить вызывать по цепочке:
class A { constructor() { this.x = 'A'; this.a = 'a'; } getOuter() { console.log('outer'); return `(${this.getInner()})`; } getInner() { console.log('a'); return this.x + this.a; } } var a = new A class Wrapper { constructor(original) { this.original = original } getOuter() { this.original.getInner = this.getInner.bind(this); return this.original.getOuter(); } getInner() { delete this.original.getInner; return this.original.getInner(); } } class B extends Wrapper { constructor(original) { super(original); this.x = 'B'; this.b = 'b'; } getInner() { console.log('b'); return `[${this.x}${this.b}][${super.getInner()}]`; } } var b = new B(a); class C extends Wrapper { constructor(original) { super(original); this.x = 'C'; this.c = 'c'; } getInner() { console.log('c'); return `<${this.x}${this.c}><${super.getInner()}>`; } } var c = new C(b); console.log(c.getOuter());

Комментариев нет:

Отправить комментарий