Как реализовать правильную связь классов в javascript? — javascript ооп полиморфизм

1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд
Загрузка...

Вопрос:


Теперь в деталях : имеются несколько классов :

class RemovedItem {
  constructor(value, key) {
    this.value = value;
    this.key = key;
}
 }
 
 class AddedItem {
  constructor(value, key) {
    this.value = value;
    this.key = key;
}
}
class ChangedItem {
  constructor(beforeValue, afterValue, key) {
    this.afterValue = afterValue;
    this.beforeValue = beforeValue;
    this.key = key;
}
}

для каждого из этих классов (их больше чем в примере но не суть) нужно реализовать собственный класс рендерер ( например RemovedRenderer для RemovedItem ) который будет выводить строковое представление итема . Дальше в некую функцию будет передаваться массив этих итемов и внутри нее как то нужно автоматически вызывать для каждого итема свой рендерер. Проверки в стиле

if (item instanceof AddedItem )

не в счет ибо такой код убивает идеи ооп .

Автор вопроса: Артём Негода

alvoro

Ну на ум приходит что то типа такого:

    class ItemType1 {
        constructor() {
            // ...
        }
    }
     
    class ItemType2{
        constructor() {
            // ...
        }
    }
     
    class ItemType3 {
        constructor() {
            // ...
        }
    }
    
    // Объект, содержащий методы для рендеринга определённых типов айтемов. 
    const render = {
        ItemType1(item) {
            console.log(1);
        },
     
        ItemType2(item) {
            console.log(2);
        },
     
        ItemType3(item) {
            console.log(3);
        }
    };
     
    [new ItemType1, new ItemType2, new ItemType3].
        forEach((item) => render[item.constructor.name](item) );

Имя метода в объекте render должно совпадать с именем класса, который планируется рендерить.

Если я правильно понял, то вам может подойти что-то такое.

class ItemBase {
  render() {
    console.log('ItemBase render');
  }
}

class Item1 extends ItemBase {
  render() {
    super.render();
    console.log('Item1 render');
  }
}

class Item2 extends ItemBase {
  render() {
    console.log('Item2 render');
  }
}

class Item3 extends ItemBase {

}

[new Item1(), new Item2(), new Item3()].forEach(e => e.render())

Если вам все же нужен отдельный класс для рендера можно сделать вот так

class BaseRenderer {
  render(item) {
    console.log('BaseRenderer render', item);
  }
}

class Item1Renderer extends BaseRenderer {
  render(item) {
    super.render(item);
    console.log('Item1Renderer render', item);
  }
}

class Item2Renderer extends BaseRenderer {
  render(item) {
    console.log('Item2Renderer render', item);
  }
}

class ItemBase {
  constructor(renderer) {
    this._renderer = renderer;
  }
  render() {
    this._renderer.render(this);
  }
}


class Item1 extends ItemBase {

}

class Item2 extends ItemBase {

}

class Item3 extends ItemBase {
  constructor() {
    super({
      render: (item) => console.log('sef-made', item)
    });
  }
}


[new Item1(new Item1Renderer()), new Item2(new Item2Renderer()), new Item3()].forEach(e => e.render())

Собственно отвечаю на свой вопрос))) :

class Type1Renderer 
{

getStyleOneString () { return `is type1 style1 ${this.value}`}
//добавление новых форматов/стилей происходит посредством добавления функции в класс рендерера
getStyleTwoString () { return `is type2 style2 ${this.value}`}

}

class Type2Renderer 
{
getStyleOneString () { return `type2 style 1 ${this.value}`}

getStyleTwoString () { return `type 2 style2 ${this.value}`}
}



//классу итема достаточно просто наследоватся от нужного рендерера
class ItemType1 extends Type1Renderer
{
constructor(value){
super();
this.value=value;
}
}

class ItemType2 extends Type2Renderer
{
constructor(value){
super();
this.value=value;
}
}

//теперь в функции каждый итем будет вызывать свой getString
console.log([new ItemType1('fiz'),new ItemType2('baz')].map(item => item.getStyleOneString()));

Источник

Вам также может быть интересно:

Переадресация запросов по данным из тела запроса — java nginx spring-mvc
Вопрос: Существует сервис с "кучей" контроллеров. Стоит задача "распилить" данный сервис на микросервисы. Сами микросервисы будут крутится на самостоятельных машинах. Основная проблема в том, что есть ...
Java. Деление в столбик. Съезжает вывод в консоль — java
Вопрос: Кто-нибудь может подсказать почему при делении 1034/15 съезжает вывод в консоль? public class Division { private StringBuffer result = new StringBuffer(); ...
Доступ к cookies другого сайта — javascript
Вопрос: Не знаю, или правильно написал вопрос в заголовке. Вообще вопрос такой. Есть, например виджет коминтариев фб, его можно установить на свой сайт. При заходе, он ...
Не видит загрузочной флешки с Ubuntu — linux windows ubuntu
Вопрос: Решил установить Ubuntu второй ОС. Скачал образ и установил его на флешку. Память для будущей Ubuntu выделил ещё когда устанавливал Windows. Проблема в том, что когда ...
Как устроен Netty? — java async netty
Вопрос: Немного почитал про асинхронные сокеты и про фреймворк Netty, но у меня возник вопрос о том как устроен механизм обработки многочисленных запросов к Netty. ...
Модификация Observable при помощи дополнительного запроса в сеть — android kotlin rxjava
Вопрос: работаю с Vk.APi и произвожу поиск списка групп. В ответе с API получаю список групп, но проблема в том, что каждая из них не содержит ...
Как загрузить Layout в Activity или View из переменной типа String — android xml activity
Вопрос: Обычно внешний вид Activity или View загружается из файлов типа *.xml, вложенных в папку res/layout проекта. А как сделать, чтобы внешний вид загружался из ...
Как выбрать максимальное значение в столбце? — sql sql-server
Вопрос: У меня есть таблица которая состоит из 2 столбцов OrderID OrderDate ------------------------------- 1021 1976-07-04 00:00:00 2312 ...
Форма TextView XML — android xml
Вопрос: Прошу понять меня правильно: Я не прошу что-то сделать за меня и предоставить готовый код ВОПРОС: Какие атрибуты необходимо использовать, чтобы выполнить такой же вид ...
Отловить закрытие консольной программы — c# console
Вопрос: Есть консольное приложение (C#), мне нужно отловить событие его закрытия. Это может быть и Ctrl+C и нажатие на крестик, вообще любое событие после которого ...
Странное поведение jQuery — jquery
Вопрос: Есть веб-страница, на которой естественно имеются стили и скрипты. При очистке кэша и полной перезагрузке страницы (Ctrl + F5) jQuery неправильно определяет height() и ...
Оверлей для любой программы и игры DirectX в фуллскрине через инжект dll — c# wpf
Вопрос: Всем привет. Хочу сделать универсальный оверлей, который при запуске из консольного приложения будет инжектить dll с самим оверлеем в любую программу, как у стима/дискорда. Про инжект ...
Использование, связка бинов в Java — java netbeans xhtml
Вопрос: У меня есть example.xhtml, я не знаю как правильно его заполнить, так как NetBeans предлагает один вариант, а видео, где все работает, заполняют по-другому.Netbeans: <?xml ...
Удалил rfremix-relese при попытке обновления — linux fedora
Вопрос: Сегодня хотел обновить Руссиан Федора Ремикс (RFRemix) 28->29. dnf upgrade выдал сообщение о конфликте в пакете rfremix-release-2.ххххххх Немного посомневался, но решил что это модуль именно ремикса ...
Компиляция QT 5.11 на Raspberry Pi 3 — c++ qt5 raspberry-pi
Вопрос: Raspberry Pi идет в комплекте с QT 5.3 и QT Creator 3.2.1. Есть необходимость обновить версию QT до 5.11. Чтобы была возможность использовать новые ...

Оставьте ответ

Ваш e-mail не будет опубликован. Обязательные поля помечены *