• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Dziedziczenie czy przekazanie obiektu klasy jako argument innej klasie

Object Storage Arubacloud
0 głosów
332 wizyt
pytanie zadane 13 czerwca 2022 w PHP przez andrzejt17 Użytkownik (680 p.)
edycja 13 czerwca 2022 przez andrzejt17

Cześć!

Czy proszę mi poradzić, co jest bardziej po bożemu? Klasa A z metodami przydatnymi każdej klasie specjalistycznej B czy C.

Klasę A z pewnymi metodami rozszerzyć za pomocą klasy B, C czy innej i z każdą instancją B czy C mieć niejako nową instancję A

czy

Stworzyć jedną instancję klasy A i z tworzeniem obiektu klasy B lub C przekazać obiekt A w argumencie? 

Aplikacja ma z 12k linijek ciąglę się biję z myślami jak to powinno działać. Sensowne wydaje się mieć jedną instancję A i podawać do każdej klasie specjalistycznej B czy C jako argument i tak zrobiłem, niemniej myśli mnie nie opuszczają.

 

class Main
{
	// general methods
}

class First extends Main
{
	// module 1 special methods
}

class Secound extends Main
{
	// module 2 special methods
}

$inst1 = new First;
$inst2 = new Secound;


class Main
{
	// general methods
}

class First
{
	private $mainClass;

	public function __construct(object $mainClass) 
	{
		$this->mainClass = $mainClass;
	}

	// module 1 special methods
}

class Secound
{
	private $mainClass;

	public function __construct(object $mainClass) 
	{
		$this->mainClass = $mainClass;
	}

	// module 2 special methods
}

$mainClass = new Main;
$inst1 = new First($mainClass);
$inst2 = new Secound($mainClass);

 

Zwykle będzie tylko jedna instancja klasy specjalizującej więc luz. Może czasem się zdarzyć że będą dwie instancje klas specjalizujących i wtedy - w mojej głowie, jest dwa razy rozszerzana klasa A, niejako duplikowana co wydaje się bezsensowne. W drugim rozwiązaniu referencja do obiektu A bez niepotrzebnego duplikowania wynikającego z dziedziczenia. Mimo wszystko kod jednak lepiej obrazuje niż ten opis :P

komentarz 13 czerwca 2022 przez adrian17 Ekspert (344,860 p.)

Uh... przy dziedziczeniu ważniejszym jest się zastanowić, czym się różnią - czy mają wspólne pola, czy nie? Czy metody są faktycznie dziedziczone, czy nie?

Zwykle będzie tylko jedna instancja klasy specjalizującej więc luz.

sus. Nie powinno być tak że każdą instancję klasy zastępujesz podklasą.

Najlepiej jakbyś pokazał jak w ogóle wygląda zawartość tych klas.

komentarz 13 czerwca 2022 przez andrzejt17 Użytkownik (680 p.)
Podejmę próbę opisania słowami, jako, że to dość duży i rozwleczony projekt.

Klasa Model
zawiera metody, które muszą być wywoływane z każdym żądaniem (połączenie z bazą, przeładowywanie uprawnień użytkownika) oraz metody, z których chcą korzystać klasy o określonej specjalizacji dorzucając swoje metody.

Klasa specjalizująca Receive
zawiera już konkretne metody (pobiera dane o przyjęciach urządzeń na serwis, dodaje kolejne przyjęcie) używając w tym metod swoich i tych dziedziczonych po Model.

Klasa specjalizująca Parts
zawiera metody zarządzania stanem części w serwisie (zamówienia, zwroty), metody swoje i dziedziczone po Model

Tyle, że można to osiągnąć na dwa wcześniej wspomniane sposoby. Czasem może się zdarzyć, że w jednym wykonaniu skryptu będę potrzebował wywołać dwie różne klasy specjalizujące. Oba wcześniej napisane rozwiązania dają mi ten sam efekt. Być może trochę za wąsko na to patrzę, nie wiem tylko skąd zaczerpnąć taką wiedzę.
komentarz 13 czerwca 2022 przez adrian17 Ekspert (344,860 p.)
Uhh... ale nigdzie nic nie napisałeś o polach?

Jak nie ma żadnego stanu, to po co w ogóle jakiekolwiek klasy i dziedziczenie, a nie po prostu zbiór funkcji za namespace'ami?
komentarz 13 czerwca 2022 przez andrzejt17 Użytkownik (680 p.)
edycja 13 czerwca 2022 przez andrzejt17
Rzeczywiście, przecież to nie tylko zbiór funkcji..

Model przechowuje np pole z uprawnieniami pobieranymi raz z bazy, by za każdym razem klasa podrzędna jej nie odpytywała. Przechowuje też pole z listą pracowników id => nazwa. Na ten moment tyle, bez wątpienia będzie więcej informacji po które będę chciał sięgać kilkukrotnie z różnych klas podrzędnych więc będę je przechowywał w polach Modelu.

 

EDIT
Po Twoim komentarzu chyba sobie zdałem sprawę, że pojęcie obiektowości nie jest dla mnie w pełni zrozumiałe i chyba na tym etapie pomoc mi nie będzie możliwa, przynajmniej sensowna.
komentarz 14 czerwca 2022 przez Wiciorny Ekspert (270,170 p.)
Model niczego nie przechowuje, modele jako klasy nie maja swojego stanu- to abstrakcyjne byty, które są jedynie szablonem.
Stosując kompozycje nad dziedziczeniem, każdy nowo utworzony obiekt może mieć własny egzemplarz, jeśli tak nie jest- to z drugiej strony mocno naginasz sam fakt niezmienności i tego, ze dążymy aby obiekty były w pewnym stopniu immutable i niezależne.

Problem z dziedziczeniem rośnie w miarę jego korzystania, kod staje się potem trudny do rozwijania, czasami nie chcesz mieć możliwości dziedziczenia po klasie B, tylko po C, bez elementów klasy B, samo zablokowanie elementów jako prywatnych tu nie pomoże, a wielodziedziczeniu np w Javie nie jest dobrym rozwiązaniem.
Stąd zawsze lepszym wyborem jest kompozycja.

Natomiast jeśli dany element, nie stanowi stanu - to najlepszym rozwiązaniem jest najwyższy poziom abstrakcji jako interfejs  [ lub jeśli ten stan jest niezmienny].
komentarz 15 czerwca 2022 przez andrzejt17 Użytkownik (680 p.)
Pojęcie kompozycji wywołało u mnie dreszcz ale jednak nie jest takie straszne. Spróbuję to zrozumieć w praktyce i wcielić w życie, dziękuję!

1 odpowiedź

0 głosów
odpowiedź 14 czerwca 2022 przez jankustosz1 Nałogowiec (35,880 p.)

Zainteresuj się wzorcami projektowymi. Z tego co piszesz dobrze sprawdziłby się wzorzec dekoratora.

Wyglądałoby to mniej więcej tak:

public class ReceiveModel extends Model{
    private Model baseModel;

    public ReceiveModel(Model baseModel) {
        this.baseModel = baseModel;
    }
}
public class PartsModel extends Model{
    private Model baseModel;

    public PartsModel(Model baseModel) {
        this.baseModel = baseModel;
    }
}

...
Gdy chcesz użyć obu:
var model = new PartsModel(new ReceiveModel(new Model()));

Nie jest to w php, ale bez problemu powinieneś zrozumieć ideę.

komentarz 14 czerwca 2022 przez Wiciorny Ekspert (270,170 p.)
zanim coś komuś doradzisz, to polecam dobrze się zastanowić czy to co proponujesz ma sens. PO drugie mocno naciągany dekorator o ile to nie jest dekorator nawet sam w sobie.

Rozszerzasz klasę, potem aby w każdym szablonie jednocześnie Model przekazać z pomocą kompozycji
Jeśli rozszerzasz klase, nie potrzebujesz przekazywać jej jako kompozytowy obiekt... wystarczy super(), po drugie  dekorator działają na podstawie interfejsu, wiec jeśli rozszerzasz cos to element kompozytowy powinien być typu Interfejsu.

Jeśli rozszerzasz Model, to model musi implementowac jakiś interfejs np. ModelIterface i on powinien byc przekazany jako kompozycja.
komentarz 14 czerwca 2022 przez jankustosz1 Nałogowiec (35,880 p.)
edycja 14 czerwca 2022 przez jankustosz1

Rozszerzasz klasę, potem aby w każdym szablonie jednocześnie Model przekazać z pomocą kompozycji
Jeśli rozszerzasz klase, nie potrzebujesz przekazywać jej jako kompozytowy obiekt... wystarczy super()

Z tego co piszesz nie wiesz jak działa wzorzec dekoratora. Właśnie o to chodzi żeby przekazywać obiekt klasy bazowej i jednocześnie po klasie bazowej dziedziczyć. Wszystkie metody klasy pochodnej są zaimplementowane poprzez wywołanie tej metody na przekazanym obiekcie i ewentualnie wykonanie jakiś dodatkowych operacji.

Dzięki temu można dany obiekt dekorować wielokrotnie różnymi dekoratorami ciągle otrzymując obiekt klasy bazowej z którego możemy wywołać potrzebne nam funkcje.

To co napisałem to pseudokod, najbliżej jest temu chyba do c#. Model może być zwykłą klasą, abstrakcyjną lub interfejsem. 

komentarz 15 czerwca 2022 przez andrzejt17 Użytkownik (680 p.)

@jankustosz1, abstrakcją dla mnie jest to jakimi pojęciami operujecie. No nic, małymi kroczkami, większość wzorców mnie przeraża i kompletnie nie widzę dla większości zastosowania. Pewnie kwestia tego, że nie spotkałem się z problemami, które one rozwiązują. Albo tych problemów zwyczajnie nie widzę. Jak żyć?

Podobne pytania

+1 głos
1 odpowiedź 855 wizyt
0 głosów
4 odpowiedzi 216 wizyt
0 głosów
1 odpowiedź 420 wizyt

92,576 zapytań

141,426 odpowiedzi

319,651 komentarzy

61,961 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...