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

176
15 ноября 2018, 21:00

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

Известно, что из метода getOuter ровно один раз вызывается метод getInner. Надо сделать так, чтобы вызывался getInner не оборачиваемого объекта, а оборачивающего. В качестве прокси используется класс Wrapper, от которого наследуются обрачивающие классы. Что надо в него дописать, чтобы работало соответствующим образом?

Желаемый вывод после дописывания врэппера:

outer
c
b
a
(<Cc><[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());

Answer 1

Ура, кажется получилось!

Надо в 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());

READ ALSO
Передать данные по нажатию кнопки

Передать данные по нажатию кнопки

Возник интересный вопрос, как мне лучше всего передавать someValue в somefunction, при нажатии кнопки: оформить все это в форму или лучше использовать...

165
Slick slider с ползунком

Slick slider с ползунком

Подскажите решение как реализовать синхронизацию ползунка с картинкамиОчевидно, но на всякий случай: Крутим ползунок вправо - слайды двигаются...

168
Работа с скролом у блока

Работа с скролом у блока

Возникло несколько моментов с прокруткой блокаПрошу заметить, тут меня не интересует прокрутка страницы, как оказалось

159
Как сделать placeholder&#39;ы под картинки при их загрузке на странице

Как сделать placeholder'ы под картинки при их загрузке на странице

Такой стиль загрузки я заметил на сайте https://unsplashcom/(Наверное всем известен ) Помогите пожалуйста , буду ждать ответа

184