Dziedziczenie - wykładniczy rozrost klas

Odpowiedz Nowy wątek
2019-08-13 06:30
0

Hej,
Mam daną klasę A, która zawiera puste metody (ma definicje ale są puste):

claas A
{
public:
  virtual void test1() {}
  virtual void test2() {}
};

Oraz klasę B, która dziedziczy po A i nadpisuje metodę test1:

class B : public A
{
public:
  void test1() override {...}
};

I teraz mam kolejną klasę, która napisuję metodę test2. Klasy C i B nie wykluczają się. Taka klasa C powinna rozszerzyć zatem klasę A ale i B. Mamy już 4 kombinacje. Dojdzie kolejną klasa, będzie 9 kombinacji.
Liczba plików rośnie wykładniczo.

Jakiś pomysł jak to zrobić dynamicznie? Myślałem nad szablonem ale definicja klas koniecznie musi znajdować się w odosobnionym pliku .cpp oraz muszę mieć decyzje, które klasy mogą rozszerzać podrzędne.

edytowany 1x, ostatnio: Focusx, 2019-08-13 06:33

Pozostało 580 znaków

2019-08-13 07:43
4

Taka klasa C powinna rozszerzyć zatem klasę A ale i B

? Po co Ci dziedziczenie z B?

To mi wyglada jakbys naduzywal dziedziczenia. Na pewno nie chcesz / nie mozesz uzyc tutaj kompozycji?

Pozostało 580 znaków

2019-08-13 09:28
4

Dobra z a teraz zamiast A, B i C napisz konkretnie jakiś życiowy przykład. Poza tym twoja klasa A wygląda na złamanie zasady separacji interfejsów i zasady podstawiania, skoro robisz klasę B która dziedziczy z A i nie nadpisuje wszystkich metod czysto wirtualnych. To ci kiedyś wybuchnie w twarz, bo ktoś zawoła sobie tą metodę.
Szklana kula mówi że powinienes mieć 2 osobne interfejsy, jeden z metodą test1 a drugi z test2.


Masz problem? Pisz na forum, nie do mnie. Nie masz problemów? Kup komputer...

Pozostało 580 znaków

2019-08-13 09:46
0

Btw, zamiast pustych metod zrób je czysto wirtualne.

Pozostało 580 znaków

2019-08-13 10:27
0
Focusx napisał(a):

I teraz mam kolejną klasę, która napisuję metodę test2. Klasy C i B nie wykluczają się. Taka klasa C powinna rozszerzyć zatem klasę A ale i B. Mamy już 4 kombinacje.
Dojdzie kolejną klasa, będzie 9 kombinacji.

Jakie kombinacje?

Pozostało 580 znaków

2019-08-13 10:37
0
Focusx napisał(a):

Liczba plików rośnie wykładniczo.

W jaki sposób?

Pozostało 580 znaków

2019-08-13 11:33
0

Z tego co napisałeś wynika, że to powinny być osobne interfejsy jak napisał Shalom. Jeżeli z jakiegoś powodu, którego nam nie podałeś, to nie mogą być osobne interfejsy, to robisz kompozycje jak napisał fasadin.
Ewentualnie mixiny, ale to zależy co dokładnie chcesz osiągnąć.
Dziedziczenie diamentowe, które próbujesz zrobić nie jest zbyt często spotykane w praktyce.

PS. Wygląda to na złe zrozumienie programowania obiektowego i nadużywania dziedziczenia.

edytowany 2x, ostatnio: nalik, 2019-08-13 11:43

Pozostało 580 znaków

2019-08-13 15:37
0

Przykład z życia (związany z OpenGL).
Klasa bazowa to obiekt 3d. Taka klasa zawiera macierz transformacji, mesh oraz shadery. Klasa dziedzicząca po niej to object3dInstanced - jedna metoda renderująca kilka obiektów na raz, z tym samym meshem (nieco zmienia jej definicje), nieco inne shadery.

Klasa bazowa (Object3d) zawiera również pustą definicje metody "void update()", która jest zawsze wywoływana w metodzie render().
Tu pojawia się klasa C, czyli SkinnedObject3d. Taka klasa może dziedziczyć po Object3d lub po object3dInstanced. Nadpisuje ona bowiem wyłącznie metodę update(). Shadery chcę zrobić by generowały się dynamicznie w zależności jaką mamy klasę nadrzędną.

Po co tak? Czemu nie używam zwykłego if'a?
A no dlatego, że do animacji obiektu pojawi się wiele nowych pól, które są zbędne dla obiektu statycznego (bez animacji szkieletowej).

Planem awaryjnym jest utworzenie wektora w klasie Object3d, który będzie zawierał dedykowane dla niej komponenty. Jak dla mnie to mniej przejrzyste będzie.

edytowany 3x, ostatnio: Focusx, 2019-08-13 15:44

Pozostało 580 znaków

2019-08-13 16:17
0

Mi to wygląda na książkowy przykład na wzorzec Composite.


Masz problem? Pisz na forum, nie do mnie. Nie masz problemów? Kup komputer...

Pozostało 580 znaków

2019-08-13 17:35
0

W zasadzie może faktycznie Kompozyt będzie najlepszy.
Dzięki za podpowiedzi.

Pozostało 580 znaków

2019-08-13 17:44
0

Pomyśl też może o tym, że klasa zwykle sugeruje że będziesz miał wiele takich obiektów, a u ciebie nie jestem pewien czy to jest prawda. Tworzenie nowej klasy tylko po to żeby nadpisać metodę bo potrzebujesz jej w jednym obiekcie, to błąd. W takiej sytuacji można pomyśleć o jakimś TemplateMethod albo o kompozycji, gdzie jednym z parametrów twojej klasy jest funkcja albo funktor.

Załóżmy że chciałbym mieć dwa obiekty klasy FooBar, jeden w metodzie test ma robić X, a drugi ma robić Y. Poza tym obiekty są identyczne (z punktu widzenia strukturalnego). Zamiast robić tutaj dwie dziedziczące z FooBar klasy, mogę po prostu w konstruktorze przekazać lambdę albo obiekt klasy Function który ma jedną funkcję, tą która mnie interesuje. A sam FooBar będzie w test odpalać function.run().


Masz problem? Pisz na forum, nie do mnie. Nie masz problemów? Kup komputer...

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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