Как реализовать правильную связь классов в 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()));

Источник

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

Использование вложенных маршрутов в React Router — javascript reactjs react-router
Вопрос: Для организации маршрутов в приложении использую React Router. <Route path="/" component={...}> <IndexRoute component={...}/> <Route path="user/:userId" component={...}> ...
Как с помощью Retrofit 2.0 отправить данные в JSON на сервер и получить ответ? — java android retrofit
Вопрос: Только начал читать про Retrofit 2.0 до этого использовал HttpURLConnection. Как я работаю с HttpURLConnection, формирую Json перевожу его в byte, ставлю header в ...
Не приходят push уведомления. FCM — android firebase android-notification
Вопрос: Появилась необходимость реализовать push уведомления. Прописал в манифесте сервис: <service android:name=".MyFirebaseMessagingService"> <intent-filter> ...
Принцип браузерной игры в линукс терминале — java linux terminal
Вопрос: Наткнулся на Java библиотеку CHARVA. И хотел бы уточнить у знающих людей, возможно ли на основе данной библиотеки сделать программу по принципу браузерной игры, но ...
Мерцание заблокированного экрана при выключенной подсветке в Debian 8 Gnome 3 — linux debian экран
Вопрос: На ноутбуке с Debian 8 Jessie и Gnome 3 имеется следующая проблема. При выключенном заблокированном экране сквозь него можно наблюдать, как весь экран становится белым, ...
Создание WCF клиента на готовый SOAP web сервер — c# wcf
Вопрос: Доброго времени суток. Появилась задача опрашивать web сервер с клиента на котором планируется написать WCF клиентскую часть. Информации про сервер очень мало (не знаю платформу ...
Безопасно ли удалить файл логов general_log.txt? — mysql
Вопрос: При выполнении запроса со вставкой данных большого объёма SQLyog начал вылетать с ошибкой: not enough memory application terminated В связи с этим я решила ...
Callback функции создания таблицы mysql в nodejs — mysql node.js callback
Вопрос: Есть функция, которая при запуске создает базу даных, function showDb() { pool.query("show databases like 'bt' ",function (err, ...
Как создать Adapter с неограниченным количеством строк и с неограниченным разным количеством столбцов в каждой строке — java android
Вопрос: Как создать Adapter с неограниченным количеством строк и с неограниченным разным количеством столбцов в каждой строке Автор вопроса: Salut Amigo Источник
Не могу передать байтовый массив в контроллер — c# asp.net-mvc entity-framework
Вопрос: У меня изображения храняться в бд в формате байтового массива, через форич отлично все выводит, но когда я хочу открыть страницу для работы с ...
proguard release error — java android mvp
Вопрос: Включил в проекте proguard, apk собирается, все хорошо, но приложение не работает) Proguard-rules.pro -keepattributes InnerClasses -keepattributes EnclosingMethod -keepattributes *Annotation* -dontoptimize # Keep Butterknife -keep class butterknife.** { *; } -dontwarn butterknife.internal.** -keep ...
Не отрабатывает page:update — javascript ruby-on-rails
Вопрос: Есть мой учебный проект на ruby. Делаю редактирование объектов с помощью JS. Сейчас работает так: Редактирую первый раз - всё нормально. Не обновляя страницу, ...
Как найти определенный символ в строке и удалить значение после него (и вместе с ним) Jquery — javascript html jquery
Вопрос: Здравствуйте, есть определенный набор строк, типа "L / Красный / 12345", как можно на странице найти их, и вырезать из них все что находится ...
Почему не работает wildcard module declaration? — typescript
Вопрос: Почему не работает такой способ декларации: declare module "*!text" {} ? Цель - использовать контент файла в переменной: import layout = require("/js/views/layouts/wnd.html!text"); или так: import layout from "/js/views/layouts/wnd.html!text"; Если ...
Как прервать 3rd-party код? — c# многопоточность .net-core
Вопрос: Есть 3rd-party код из библиотеки который "зависает" в ожидании где-то в работе с сетью. CancellationToken поддержки нет, таймаутов нет. Запускаю я его через: Task.Run(() => ...

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

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