Łączenie klas / dodawanie zewnętrznej metody do istniejącej klasy

0

Cześć! Mam pytanie dotyczące dodawania zewnętrznie includowanej metody do istniejącej klasy - tj. w jaki sposób to zrobić.

Mój kod:

class moja_klasa{
  konsola_1(str){
    console.log(str);
  }
}


class element_1{
  konsola_2(str){
    console.log(str);
  }
}

class element_2{
  konsola_3(str){
    console.log(str);
  }
}


Object.setPrototypeOf(moja_klasa.prototype, element_1.prototype);

const moj_element = new moja_klasa();

moj_element.konsola_2("hello 1!");

Pytanie 1: w jaki sposób połączyć wszystkie trzy klasy, jeżeli użyję kodu:

Object.setPrototypeOf(moja_klasa.prototype, element_1.prototype);
Object.setPrototypeOf(moja_klasa.prototype, element_2.prototype);

to nie działa poprawnie.

Natomiast kod:

Object.setPrototypeOf(moja_klasa.prototype, element_1.prototype);
Object.setPrototypeOf(element_1.prototype, element_2.prototype);

Działa, ale klasy byłyby łączone na powiedzmy trochę losowe sposoby i wolałbym uniknąć "zapamiętywania" kolejności.

Pytanie 2: W jaki sposób wykonać metodę/funkcję w mojej połączonej klasie, przy założeniu, że nazwę metody mam zapisaną jako np. string, coś w stylu:

let f = 'konsola_1';
moj_element.f("hello 1!");
0

Nie żebym na JS się znał ... ale jakie zaniedbanie/pomyłkę projektowe ma to naprawiać ?
Z czego ma to projekt wyciagnąć ? Z jakim XY problemem się kopiesz ?

Te extra metody muszą być z klas, a nie mogą być "jakimś" function, w duchu pełnego podrecznikowego Duck typing ?

Albo mówiąc koncepocjami języków o stabilnym pomyśle na obiektowość, jaki tu wzorzec ma zapracować

0

@ZrobieDobrze: Generalnie to chcę sobie napisać prosty edytor WYSIWYG z możliwością dołączana pluginów. Zatem chodzi mi o to, żeby do głównej klasy dodać nowe "funkcjonalności".

4

Jeśli chcesz po prostu stworzyć obiekt, który zawiera metody z różnych innych obiektów to można to łatwo zrobić na zwykłych obiektach, które posłużą jako takie "mixiny":

const a = {
  konsola_1(str){
    console.log(str);
  }
};

const b = {
  konsola_2(str){
    console.log(str);
  }
};

const c = {
  konsola_3(str){
    console.log(str);
  }
};

// tworzymy obiekt, który będzie zawierał jednocześnie rzeczy z a, b oraz c
const d = Object.assign({}, a, b, c); 
// alternatywnie możemy użyć spread operator (...) 
// const d = { ...a, ...b, ...c};

console.log(d); 
/* console.log nam loguje:
{
  konsola_1: [Function: konsola_1],
  konsola_2: [Function: konsola_2],
  konsola_3: [Function: konsola_3]
}
*/
1

Co do pytania nr 2 to możesz użyć zapisu podobnego do tablicy

const methodName = 'toString';
const wysiwyg = {};

wysiwyg[methodName](); // [object Object]

Wywołując metodę zdefiniowaną wewnatrz klasy musimy skorzystac z this

class Wysiwyg {
  constructor() {
    const methodName = 'toString';

    this[methodName]();
  }
}

new Wysiwyg();
1
catshy napisał(a):

Pytanie 2: W jaki sposób wykonać metodę/funkcję w mojej połączonej klasie, przy założeniu, że nazwę metody mam zapisaną jako np. string, coś w stylu:

let f = 'konsola_1';
moj_element.f("hello 1!");
const f = 'konsola_1';
moj_element[f]("hello");
1
Riddle napisał(a):
const f = 'konsola_1';
moj_element[f]("hello");

Problem w tym, że obiekty domyślnie mają już metody typu toString czy inne dziedziczone z obiektu bazowego Object, które mogą zaburzać potem działanie programu.

Jak chce się coś podobnego robić, to można zamiast tworzyć obiekt tak:

const a = {};
console.log(a.toString); // [Function: toString]

to tworzyć go w specjalny sposób:

const b = Object.create(null)
console.log(b.toString); // undefined

tym sposobem obiekt nie będzie dziedziczył z Object (bo dajemy null), więc nie będzie miał różnych dziwnych metod w środku.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create

alternatywnie możemy użyć metody Object.hasOwn np.

if (Object.hasOwn(someObject, methodName)) {
   someObject[methodName]();
}

wtedy sprawdzimy, czy faktycznie metody należą do tego konkretnie obiektu, a nie są odziedziczone.

0
catshy napisał(a):

@ZrobieDobrze: Generalnie to chcę sobie napisać prosty edytor WYSIWYG z możliwością dołączana pluginów. Zatem chodzi mi o to, żeby do głównej klasy dodać nowe "funkcjonalności".

Nie wiem jak wyczuwasz słwo 'Plugin' - dla mnie nie ma się on rozpuścić w zupie klasy głównej, a zachować tożsamość.
Ma więcej metod niż podstawową 'doYoyrJob() jak np specjalizowane Undo, integracje menu szare / aktywne zależnie od kontekstu itd...

A klasa główna ma prawo do swoich zmiennych prywatnych itd i nawet plugin nie może oszukiwać ...

Raczej kolekcja Pluginów niż ich rozpuszczenie w main. I "tylko" zostaje pytanie jak te niezależne pluginy wywołać

1

jeszcze zamiast wrzucania metod do jednego worka można oprzeć pluginy o eventy.
Czyli każdy plugin zamiast definiować jakieś unikalne metody do wywoływania, mógłby definiować po prostu eventy, które łapie. Coś jak to:

const myPlugin = {
    onActivate(event) {
      //....
    },
    onDrop(event) {
       // jesli to wysiwyg, to moglby definiowac event onDrop
    }
};

const otherPlugin = {
    onDrop(event) { 
      // ....
    }
}

Przez eventy mam na myśli koncepcyjne eventy. Żeby je podpiąć pod rzeczywiste zdarzenia w apce (takie lecące z przeglądarki), to już silnik pluginów by musiał nad tym panować.
Np. przy odpalaniu jakiegoś eventu, silnik przejeżdżałby przez pluginy i patrzył, czy jakiś plugin się nie podpiął pod dany event (ale mógłby patrzyć tylko po aktywnych w danym kontekście pluginach. Np. załózmy, jeśli to WYSIWYG, że masz plugin do dołączania filmików z Youtube, który definiowałby widżet do osadzania filmików. Wtedy jakby ktoś kliknął/zaczął przeciągać ikonkę danego widżetu, to aktywowałby się plugin i twój silnik pluginów by później wywoływał zdarzenia na nim typu onDrop).

1
LukeJL napisał(a):

jeszcze zamiast wrzucania metod do jednego worka można oprzeć pluginy o eventy.
Czyli każdy plugin zamiast

Tak. generalnie plugin jako jakaś zaprojektowana rzecz.
Zapisanie sie na event, zapisanie sie na typ pliku, dodanie menu i reagowanie na użycie ...

Z całą pewnością plugin to nie jedna metoda.

1 użytkowników online, w tym zalogowanych: 0, gości: 1