Wymiana klas w programie

1

Witam,

chciałbym się dowiedzieć jak w praktyce mam zrealizować wymianę referencji do klas, tak aby jedna mogła wykonywać metody drugiej. Gdybym w praktyce chciał przesyłać je przy pomocy parametrów podczas tworzenia kolejnych klas, niektóre konstruktory byłyby szerokie na dwa ekrany. Dziedziczenie odpada, zastanawiam się nad stworzeniem jednej klasy gdzie będę trzymać wszelkie referencje do klas, jednak nie wygląda mi to na zbyt eleganckie rozwiązanie. Jakieś pomysły?

0

Doszedłeś właśnie do problemu z którym borykały się zastępy programistów. Nazywa się to Dependency Injection (po polsku Wstrzykiwanie zależności) i jest milion sposobów aby ten problem rozwiązać. Najpopularniejsze rozwiązanie to takie wykorzystujące tzw kontener IoC który zajmuje się "tworzeniem" obiektów. Są na przykład frameworki takie jak Guice które pozwalają używać adnotacji do wstrzykiwania. Masz też takie zabawki jak Spring który umożliwia wstrzykiwanie za pomocą adnotacji oraz odpowiednich informacji w XMLu. Poczytaj ;)

0

To zależy od sytuacji.

Czemu klasy u Ciebie mają tylu współpracowników?

Intuicja dobrze Ci podpowiada, że długie listy parametrów do jakichkolwiek funkcji -- w tym konstruktorów -- są be. I że posiadanie jednej klasy z referencjami do pozostałych też jest na ogół be (poza specyficznymi przypadkami, np. gdy klasa ta jest rejestrem czy udostępniaczem usług).

Zwykle trzeba po prostu zrefaktoryzować hierarchię klas w strukturę bardziej... drzewiastą. Niech klasy mają niewielką liczbę współpracowników, np. 1-2. Referencje do nich możesz przekazać w konstruktorze. Niech ci współpracownicy mają z kolei swoich współpracowników i tak dalej.

Ale uwaga: nie chodzi o to by w jakiejś klasie odwoływać się do współpracowników naszego współpracownika, tj. by pisać łańcuszki w stylu:

 Pozycja poz = this.bieżącyStatek().dajUrządzeniaNawigacyjneNaMaszcie().dajGPS().dajPozycję();

Takie łańcuszki łamią prawo Demeter dla funkcji ( http://en.wikipedia.org/wiki/Law_of_Demeter ). Nie chodzi o to, że zawsze trzeba stosować się dokładnie do Prawa Demeter, ale warto mieć je na uwadzę i unikać szczególnie długich łańcuszków.

One są złe nie tylko dlatego, że głupio wyglądają, ale również dlatego, że pokazują szczegóły implementacyjne, które chcielibyśmy ukryć. W powyższym przykładzie chcemy od statku wyciągnąć pozycję, a musimy wiedzieć, że statek ma jakiś masz z urządzeniami nawigacyjnymi i że używa GPS-a do wyznaczenia swojej pozycji. Tymczasem klasa Statek powinna po prostu udostępniać odpowiednią, bezpośrednią metodę:

 Pozycja poz = this.bieżącyStatek().dajPozycję();

To, że statek poprosi o pozycję swojego współpracownika (MasztUrządzeńNawigacyjnych), który z kolei wybierze odpowiedni sposób (być może GPS, a może -- w razie awarii -- czujnik gwiezdny), to już szczegóły, których my nie musimy wiedzieć.

Generalnie ciężko Ci udzielić KONKRETNEJ rady (tj. krok po kroku co trzeba zrobić), nie mając odpowiedniego kontekstu i wiedzy o Twoim systemie. Masz jednak rację, że coś tu śmierdzi i nadaje się do refaktoryzacji: klasy powinny mieć mniejszą liczbę współpracowników. Nie powinny być ze sobą ściśle powiązane.

0

Dzięki za odpowiedzi, na poważnie wrócę do tego jutro (dziś).

Jeżeli pytacie o kontekst, to sytuacja w aplikacji wygląda mniej-więcej tak:
Tworzę okno aplikacji. W oknie jest panel. Panel ma swojego rysownika, który przygotowuje mu obraz. Rysownik z kolei ma szkicownika, który przygotowuje mu poszczególne elementy sklejane w całość przez rysownika. Obydwie te klasy pobierają informacje z klasy Ustawienia, którą modyfikuje inne okno. Po naciśnięciu przycisku w programie zaczyna się wykonywać akcja, która zmienia coś w klasie Projekt i przerysowuje panel. Tak jeszcze z 10 klas..

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