Nauka wykorzystania obiektowości

0

Witam
Postanowiłem sie nie rozpisywać i sprobuje podołac ;).

Otóż borykam sie z takim problemem.. Od jakiegos czasu ucze sie javy, a jezyk bardzo obiektowy podobno. Do tej pory pisałem w C i tak własciwie kazdy program wykonywał sie w mainie lub ewentualnie w jakichs małych funkcjach (tudzież metodach w javie) i wywoływany w mainie.

W Javie natomiast zostałem zbombardowany mechanizmem jakim jest polimorfizm - wszelkie dziedziczenia, konstruktory, słówka this/super, hermetyzacja i inne pojecia charakterystyczne dla obiektowosci.

Chce napisac program, taki mini-dziennik uczniów. Ma on czytac z pliku .txt liste uczniow, dodawac uczniow, dodawac oceny uczniowi, dodawac uwagi itd.
Napisalem juz taki w C, jednak tam jak mowilem - wszystko działo sie w obrębie jednego pliku C - main + pare funkcji i na tym koniec.

Zapewne piszac to samo w javie zrobie ogromny blad - bo nie wykorzystam pojecia obiektowosci - wiec cały moj kod bedzie mozna o kant d**y rozbić jak to mówią.

Stąd pytanie z tej mojej gadaniny można wyciagnac nastepujace: czy używania obiektowosci naucze sie z czasem czy potrzebuje zrobic cos konkretnego? Nie wiem, kiedy mam stworzyc nowa klase, a kiedy nie. Kiedy stworzyc konstruktor i do czego go stworzyć, a kiedy nie. Po co właściwie mam używac obiektowosci? Czy pole może miec przypisywaną wartosc w jakiejs metodzie (mimo zasady hermetyzacji) czy musze koniecznie stworzyc setter i odwołąc sie do settera w jakiejs metodzie?

Pojawia sie setki pytan - nie prosze zebyscie na wszystkie mi odpowiadali (choc chetnie bym tego wysłuchał :D) ale chce byscie zrozumieli sens i moje zaniepokojenia wobec mojej przyszłości z obiektowościa wsrod nauki wybornej sztuki jaka jest programowanie. :)
Co możecie mi powiedziec na ten temat? naucze sie tego z czasem?
obecnie odnosze wrazenie ze jest mi to kompletnie nie potrzebne - przeciez napisze wszystko w jednej klasie i tez bedzie działało..
Moze przez to ze pisze zbyt drobne programy? moze przyda sie dopiero we wiekszych projektach? jesli tak - wyczuje, ze musze tworzyc nowe klasy itp?

Ah namieszałem.. namieszałem.. mysle ze mnie zrozumieliscie! ;)

pozdrawiam!

0

pojawiał mi się błąd łączenia z MySQL - przez przypadek wstawiłem 4 tematy. prosze o usunięcie 3 z nich
prosze wybaczyc ;)

0

Celem programowania obiektowego jest uproszczenie API oraz umożliwienie wprowadzania bezbolesnych zmian w implementacji poprzez tworzenie kolejnych warstw abstrakcji.
Staraj się wyobrażać obiekty jako rzeczywiste przedmioty agregujące dane lub przetwarzające je (takie narzędzia). Przykładowo tworząc model dla swojej aplikacji dzienniczka, możesz utworzyć klasy takie jak Dzienniczek, Uczeń, Ocena, Uwaga, Nauczyciel, Przedmiot itd.
Następnie zastanów się co chcesz zrobić z tym modelem - przykładowo chcesz go wyświetlić na ekranie, ale przed tym trzeba skądś wziąć te dane prawda? (chyba że zakładamy, że dzienniczek ma przechowywać swój stan tylko na czas działania programu)
Stąd wychodzi potrzeba stworzenia jakiegoś narzędzia, które zapisze/wczyta stan modelu do jakiejś bazy danych (np. do pliku), czyli tworzymy klasę (a najlepiej interfejs, co się przyda zwłaszcza potem przy tzw. mockowaniu gdybyśmy chcieli testować klientów tej klasy) np. ModelService, z metodami typu zapisz, wczytaj, utwórzNowy. Po jakimś czasie możesz zdecydować o zmianie sposobu dostępu do danych, np. przez bazę danych SQL, wtedy jeśli ModelService był interfejsem można łatwo podmienić implementację na inną przekazując gdzieś po prostu inny obiekt.
Ostatecznie chcemy żeby użytkownik mógł zobaczyć te dane i manipulować nimi, a więc pojawia się potrzeba utworzenia kolejnej klasy - widoku. Dobrze się tutaj sprawdza wzorzec View/Controller, który każdemu widokowi (np. okienku) przyporządkowuje pewien kontroler, który obsługuje zdarzenia od użytkownika, a zatem implementuje właściwą logikę programu, poza tym taki rozdział umożliwia testowanie logiki dzięki możliwości mockowania widoku.
Trzeba pamiętać o tym, by decyzje o wprowadzaniu nowych warstw abstrakcji dobrze zracjonalizować inaczej można "przeinżynierować" aplikację przez co będzie z niej ciężko korzystać i wprowadzać zmiany, w takiej sytuacji już lepiej żeby kod był napisany nieobiektowo :).
Z innych dobrych praktyk, to najlepiej w publicznych klasach zawsze hermetyzować pola poprzez uczynienie ich jako private. W Javie to brzydko wygląda jak jest dużo setterów i getterów, ale na szczęście nie musisz ich ręcznie pisać bo wszystkie poważne IDE mają generatory kodu.
Generalnie nowe klasy powinno się tworzyć tylko w sytuacji kiedy chcesz coś logicznie oddzielić. Polecam poczytać o wzorcach projektowych, poza tym jest sporo książek nt. OOAD którymi się warto zainteresować.
Co do tego czy dasz radę, to jak będziesz wytrwały to na pewno się w końcu nauczysz :), w zasadzie każdy programista na początku zadawał sobie takie pytania jak Ty tutaj.

0

Dzieki za wyczerpujaca odpowiedz @axxxxx ;) o to chodziło
W zasadzie prawie rozumiem to co napisałes, ale szczerze powiedziawszy - plan miałem zupełnie inny, a niewpadłbym na to co ty nigdy w zyciu
Teraz pytanie skad nabyc umiejetnosc kreowania sobie takich projektow w glowie?
Jak zrobic tak, zeby wszystko co stworze było poukładane tak, ze jesli bede potrzebował tego uzyc kiedys to to uzyje bez komplikacji?

Czyli przykładowo - jesli stworze ten moj program dziennika działajacy z poziomu konsoli, a po poznaniu swinga (ktorego jeszcze nie znam) stwierdze - "o! zrobie program z interfejsem uzytkownika! ladnie bedzie wygladalo!" i bede chciał przypasowac to co juz napisalem z linii komend do graficznego interfejsu to zeby kod był podatny na taka zmiane - zeby nie wyszło tak ze wszystko mozna skasowac i wlasciwie napisac od poczatku bo szybciej bedzie na nowo niz zmieniac 3/4 kodu. I skad ja wtedy bede wiedział co ja wlasciwie mam zrobic :D czy klase, czy interfejs, a moze klase abstrakcyjna? i co w nich implementowac?:D

Pytan mam setki, tysiace a nawet dziesiatki tysiecy - moze jestem troche za bardzo dociekliwy ^^ ale cholernie mnie to interesuje, mam zapas zapału do programowania (odpukać w niemalowane!)

Rozumiem, ze chcąc wejsc na kilimandżaro - musimy isc na kilimandżaro. Inaczej mowiac - chcac umiec obiektowosc mamy sie uczyc obiektowosci. I tak robie - "na sile" wpycham w moje projekty jak tylko moge ta obiektowosc zeby tylko cos tam załapać z niej - i w sumie nie wiem od ktorej strony sie do tego zabrać, bo co nie zrobie to czuje ze robie zle, pytam na forum i okazuje sie ze faktycznie, tragedia nie warta tlumaczenia i zostaje zbesztany z błotem.
Stad moje objawy biora swoje zrodlo - nie wiem jak to pojąć :D Czytam ksiazki, poradniki - ale tam jest to podzielone na poszczegolne tematy, a jak wymysle cos swojego to budze sie z reka w nocniku

i znowu sie rozpisalem.. :)

0

Jak zrobic tak, zeby wszystko co stworze było poukładane tak, ze jesli bede potrzebował tego uzyc kiedys to to uzyje bez komplikacji?

I to jest chyba największy problem w inżynierii oprogramowania - jak tworzyć oprogramowanie, które można łatwo modyfikować. W przypadku z tą konsolą, najlepiej zastanowić się jakie zmiany mogą nastąpić, i stworzyć takie interfejsy, by można było stworzyć inną implementację bez zmian w kodzie który z nich korzysta, np. jeśli zakładamy, że w przyszłości być może zrobi się z tego aplikację webową, to trzeba potworzyć nowe interfejsy, które by zawierały w sobie operacje typu np. dodaj ocenę, zamiast robić to bezpośrednio na modelu, bo takie coś nie ma raczej sensu w aplikacji z której może korzystać kilku naraz użytkowników i potrzebne będą m.in. jakieś mechanizmy synchronizacji czy cache'owania. Dopóki korzystamy tu z widoków konsolowych/swingowych to nie trzeba implementować jakiejś złożonej logiki, i implementacje tych interfejsów mogą działać bezpośrednio na modelu, więc na ten moment będzie to nadmiarowy kod (zbędna warstwa abstrakcji), ale w przyszłości się to może zwrócić. Poza tym jak się dobrze napisze klasy z logiką (kontrolery) to podmiana implementacji widoku sprowadzi się tylko do odpowiednich przekierowań do kontrolerów (albo i bezpośrednio do nich, np. w JavaFX można wskazać w FXML-u handlera danej akcji w kontrolerze, z tym że tam jest trochę głupio zrobione, że wstrzykuje kontrolki do tej samej klasy co ta która obsługuje zdarzenia, możliwe że da się zrobić coś w stylu onAction="#getController().handleCośtam").
Co do podejścia do projektowania to chyba dobrym pomysłem jest obserwacja jak to robią inni, ja np. polecam przyjrzeć się API biblioteki Google Guava - korzysta z najlepszych praktyk programistycznych jakie dotąd wymyślono (poza tym mają bardzo zdrowe podejście do wprowadzania nowinek, każda funkcjonalność musi być solidnie zracjonalizowana i np. niepewny kod jest oznaczony adnotacjami Beta), poza tym warto ją poznać bo praktycznie w każdym projekcie się przydaje :).

Pytan mam setki, tysiace a nawet dziesiatki tysiecy - moze jestem troche za bardzo dociekliwy ^^ ale cholernie mnie to interesuje, mam zapas zapału do programowania (odpukać w niemalowane!)

Pytaj śmiało :) ja bardzo chętnie odpowiem, zawsze odpowiadając na pytania samemu się czegoś można nauczyć, gdyż zmusza to do różnych przemyśleń.

0

Jak myślisz kiedy warto korzystać z tych wszystkich wymienionych technik? Czy wprowadzałabyś tyle szumu dla projektu do 10-15K linii?

0

W przypadku z tą konsolą, najlepiej zastanowić się jakie zmiany mogą nastąpić, i stworzyć takie interfejsy, by można było stworzyć inną implementację bez zmian w kodzie który z nich korzysta[...]

Jesli chodzi o interfejsy - nie bardzo rozumiem po co je tworzyc. Wiem ze przechowuja one metody, ktore nie maja ciała ani nawet nawiasow. Powiedzmy ze to zbior metod ktore MUSZA byc zaimplementowane w klasie implementujacej ten interfejs, ale wlasciwie po co to? zeby nie zapomiec dodac jakiejs metody w klasie? :D

Co do podejścia do projektowania to chyba dobrym pomysłem jest obserwacja jak to robią inni, ja np. polecam przyjrzeć się API biblioteki Google Guava - korzysta z najlepszych praktyk programistycznych jakie dotąd wymyślono [...]

No wlasnie, a co to wlasciwie jest to google guava? zbior takich samych klas jak w standardzie javy, robiacych to samo - tylko latwiej i szybciej?
Wiele nazw sie przetoczyło przez moja nauke do tej pory - min apache Wicket, google gwt, hibernate, J2EE, jsf jsp i reszta z prefiksem "j", wszystkie do czegos sa, ale nie wiem jak ulozyc sobie je w glowie.. moze troche za wczesnie na to?

Ciekawi mnie najbardziej - kiedy stosowac te mechanizmy obiektowosci.. kiedy to sie przyda, a kiedy nie? Kiedy tworzenie interfejsu/klasy/kl. abstrakcyjnej bedzie zbedne i tylko utrudni prace (bedzie kolejna, zbedna wersja abstrakcji - jesli dobrze rozumiem ;) )? Co zrobic zeby sie nauczyc takiego.. nazwijmy to "produktywnego" stosowania założen obiektowosci?

No i wazna sprawa ktora mnie spokoju nie daje jak mowilem :D magiczna hermetyzacja..
przykład:
mamy klase "wspolrzedne", w tej klasie sa 2 pola - powiedzmy "x" i "y"
samo nadanie im modyfikatora "private" oznacza, ze zahermetyzowalismy, jesli moge tak powiedziec, te pola. Znaczy ze od tego momentu hermetyzacja jest "wykonana" czyli programista spelnil swoje zadanie? w koncu dostep do pol bedzie tylko z wnetrza klasy, a z zewnatrz nie?
No i teraz sedno sprawy: mam x i y, dalem im private, robie dla obu pol settery i gettery. Teraz tak: chce stworzyc jakies 2 konstruktory.
1 - domyslny, x i y ma wartosc 0
2 - uzytkownik nadaje wartosc w nawiasach (czyli cos w stylu: jakis_obiekt.wspolrzedne(wartosc_x, wartosc_y); )

I pytanie: tworzac te konstruktory w pierwszym ma to wygladac:

setX(0);
setY(0);

czy raczej

x = 0;
y = 0;

No i w drugim konstruktorze to samo, dac

setX(x);
setY(x);

czy raczej

this.x = x;
this.y = y;

Bo teoretycznie (tak mi sie wydaje tylko) jak juz dalem polu private - to hermetyzacja jest, a to czy dam wartosc setterem czy przypisze wewnatrz klasy sztywno, to nie jest istotne?
Czy moze zle mi sie wydaje, musze WSZEDZIE gdzie chce nadac wartosc uzyc settera?

Troche sie rozpisalem.. jak zwykle :D ale mam nadzieje ze bedzie ci sie chcialo to przeczytac @axxxxx

Pytaj śmiało ja bardzo chętnie odpowiem, zawsze odpowiadając na pytania samemu się czegoś można nauczyć, gdyż zmusza to do różnych przemyśleń.

Bardzo mnie to cieszy, ze wreszcie ktos jest chetny zeby mi troche powyjasniac i rozjaśnić sprawe :)

Jak myślisz kiedy warto korzystać z tych wszystkich wymienionych technik? Czy wprowadzałabyś tyle szumu dla projektu do 10-15K linii?

Wlasciwie to zalezy.. w jednym pliku moge przeciez stworzyc duzo klas, wiec po co tworzyc kolejne klasy publiczne.. hmm.. a z drugiej strony moze kiedys chcialbym z tego skorzystac, wiec klasa musi byc publiczna? Szczerze powiedziawszy - nie wiem, zalezy co chcialbym zrobic ;)

EDIT:
i wlasciwie.. co oznacza this? bo czesto widuje cos w stylu this.x albo this.nazwa_metody, albo po prostu this(cos_tam_w_nawiasie) i za cholere nie moge wymyslic o co tutaj sie rozchodzi ^^

0

Jesli chodzi o interfejsy - nie bardzo rozumiem po co je tworzyc. Wiem ze przechowuja one metody, ktore nie maja ciała ani nawet nawiasow. Powiedzmy ze to zbior metod ktore MUSZA byc zaimplementowane w klasie implementujacej ten interfejs, ale wlasciwie po co to? zeby nie zapomiec dodac jakiejs metody w klasie?

Interfejs określa co dany obiekt robi, nie mówi za to nic jak to jest wykonane, np. masz dwie główne implementacje interfejsu Set -> TreeSet i HashSet, obie z zewnątrz zachowują się tak samo, ale ich jakby skutkiem ubocznym jest m.in. różna wydajność.
Interfejsy stosujesz gdy interesuje Cię tylko pewna okrojona funkcjonalność, np. mając klasę Garaż, która przechowuje Samochód interesuje Cię tylko czy dany samochód zmieścisz do garażu (np. sprawdzając to przez metodę samochód.getWysokość()), to jaki to jest konkretnie rodzaj samochodu jest nieistotne dla garażu.
Wydaje mi się, że najczęściej z interfejsów korzysta się jako różnego rodzaju callbacki, np. klasa Thread wymaga implementacji interfejsu Runnable, który zostanie wywołany w nowym wątku, pisanie aplikacji w Swingu to tak naprawdę event-driven programming opierający się na implementacji listenerów do zdarzeń pochodzących od użytkownika.

Ciekawi mnie najbardziej - kiedy stosowac te mechanizmy obiektowosci.. kiedy to sie przyda, a kiedy nie? Kiedy tworzenie interfejsu/klasy/kl. abstrakcyjnej bedzie zbedne i tylko utrudni prace (bedzie kolejna, zbedna wersja abstrakcji - jesli dobrze rozumiem )? Co zrobic zeby sie nauczyc takiego.. nazwijmy to "produktywnego" stosowania założen obiektowosci?

Dlatego należy dobrze racjonalizować każdą decyzję projektową, gdyż stworzenie aplikacji w której każdy obiekt ma swój interfejs i fabrykę i od tego jeszcze jakiś builder to żadna sztuka :). Z reguły taka wiedza przychodzi z doświadczeniem.

Co do hermetyzacji to stosuje się ją przede wszystkim dlatego, że udostępniając pola nie mamy kontroli nad tym co klienci danej klasy z nimi zrobią. Powoduje to np. problemy z synchronizacją, jak wiele wątków chce modyfikować stan obiektu, musimy wtedy pamiętać żeby zrobić synchronize na całym tym obiekcie albo wykorzystać jakiś lock, co też powinno być udokumentowane. Jeśli wszystko ukryjemy wewnątrz klasy to możemy łatwo zdefiniować obszary wykluczające się za pomocą różnych narzędzi (ogólnie polecam książke na ten temat pt. Java Concurrency in Practice). Generalnie hermetyzację stosuje się tylko w publicznym API, możesz sobie w prywatnych klasach odwoływać się bezpośrednio do pól.

przykład:
mamy klase "wspolrzedne", w tej klasie sa 2 pola - powiedzmy "x" i "y"...

To czy zrobisz setX(x) czy this.x = x w konstruktorze nie ma żadnego znaczenia :). Chyba że setter robi coś innego poza ustawieniem pola (np. powiadomienie jakichś listenerów o zmianie, albo rzucenie eventa na jakiegoś event busa) i nie chcesz żeby się to zdarzyło w konstruktorze.
Słowo this oznacza "ten" obiekt czyli jakby kontekst w którym wykonujemy daną metodę, w zasadzie nawet w C można by uprawiać takie programowanie pseudoobiektowe, robiąc coś w tym stylu (dawno nie pisałem w C więc pewnie nie będzie to poprawny kod):

typedef struct {
    // Pola
    int pole;

    // Metody
    void (metoda*) (Klasa* this, int x);
} Klasa;

Klasa* konstruktor(int parametr) {
    // Tworzymy obiekt w pamięci i ustawiamy wskaźniki funkcyjne na metody
    Klasa* obiekt = malloc(sizeof(Klasa));
    (*obiekt).metoda = Klasa_metoda;
    (*obiekt).pole = parametr;
    return obiekt;
}

void Klasa_metoda(Klasa* this, int x) { // implementacja metody
    (*this).pole = x;
}

void jakaśMetoda() {
   Klasa* obiekt = konstruktor(5);
   (*obiekt).metoda(obiekt, 10); // Przekazujemy w pierwszym parametrze "siebie"
}

A Google Guava to taka biblioteka z utilami do ogólnego użytku, możesz tutaj poczytać na wiki jakie ma możliwości - https://code.google.com/p/gua[...]ries/wiki/GuavaExplained?tm=6

0

Nie bylem dostepny dosc dlugo bo mialem sporo nauki, dlatego dopiero teraz odpisuje ;)

Interfejs określa co dany obiekt robi, nie mówi za to nic jak to jest wykonane ...

Czyli.. wlasciwie po co one sa? zawieraja one metody bez implementacji, same nazwy. Wiec implementujac interfejs MUSZE WSZYTKIE metody z interfejsu w klasie utworzyc, potem dodac im jakas funkcjonalnosc i na koncu beda dzialac. Tak wiec rownie dobrze, moglbym zapisac sobie w notatniku czy zeszycie, ktore metody chce utworzyc i po prostu stworzyc obiekt klasy ktora ma metody mnie interesujace i tyle - byloby latwiej, mniej pisania, mniej zawile :D
Sprawe interfejsow i klas abstrakcyjnych tak wlasnie rozumiem - i jestem pewien ze rozumiem zle, bo w tym wypadku byloby to zbednym obciążeniem :) Czemu np zabrierac klasie mozliwosc tworzenia jej obiektu (czyli tworzyc klase abstrakcyjna)? nie moge sobie tego poukładac w łepetynie

Co do hermetyzacji - jeszcze nie przerabialem wielowątkowosci itp, dlatego nie wiem jak to z tym jest. Generalnie interesuje mnie czy moge wrzucic polu wartosc w klasie tak po prostu, np czy moge polu typu string przypisac łancuch tak ze majac

private String lancuch;
//przypisze temu polu jakis tekst
[..]
lancuch = "jakies zdanie do lancucha";

Czy to jest poprawne dzialanie? Nie uczy złych praktyk?

No i oczywiscie, ktore rozwiazanie jest bardziej trafione: (pola mamy dwa: private int x i y)


x = 0;
y = 0;

czy moze bardziej

this.x = 0;
this.y = 0;

W prawdzie oba sposoby daja wartosc polu, pytanie czym to sie rozni :D? zapewne majac metode ktorej przekazujemy np parametry x i y w nawiasach, musimy napisac this.x = x; zeby odroznic pole od tej zmiennej wprowadzanej do metody (nie wiem jak na takie zmienne sie mowi :D)

Mozesz mi zarzucac przykladami javowskimi - bo C mam w szkole i wlasciwie nie jestem tam na az tak wysokim poziomie.
Tak prawde mowiac - to ja lamer i słabiak jestem w znajomosci jezykow. Do tej pory mi to fajnie szło, wiec postanowilem sie z tematem zapoznac troche bliżej bo mnie to interesuje i robią sie schody z tego co widze ;) ciezko to ogarnac.. nie mam pomyslu jak sie tego nauczyc, czytam co mi polecasz i co wyczytam w internecie i tak codzień własciwie i mam wrazenie ze stoje w miejscu, a nawet sie cofam:D

Kuźwa cięzko.. ciezko^^ jak to pojac
@axxxxx

0

Nadal nie rozumiesz po co są interfejsy :). Nie chodzi tu o to, żeby do każdej klasy tworzyć interfejs tylko by wypisać jakie ma ona metody. Służą one stworzeniu pewnej abstrakcji, zwłaszcza kiedy mamy do czynienia z wieloma implementacjami czegoś. Wymyśliłem taki przykład, jest to prosty symulator procesora:

class Procesor {
private List<Komenda> komendy;
private KontekstProcesora kontekst;

public Procesor(List<Komenda> komendy) { // nazywamy tutaj parametr tak samo jak pole klasy -> w Javie jest to dozwolone
this.komendy = komendy; // this.komendy to pole wewnątrz klasy, piszemy tak, bo parametr konstruktora je przesłania
kontekst = utwórzKontekst(); // załóżmy że gdzieś tam jest implementacja...
}

public void start() {
while (warunek do zakończenia działania, np. kontekst.getLicznik() >= komendy.size()) {
// Tutaj pobieramy instrukcję z listy komend i ją wykonujemy, jak widać nie obchodzi nas jaka to jest
// konkretnie komenda, wiemy tylko że może coś zrobić z kontekstem
komendy.get(kontekst.getLicznik()).wykonaj(kontekst);
// poza tym this przed kontekst jest niepotrzebne bo go nie przesłaniamy
}
}

}

interface KontekstProcesora {
int getLicznik();
// gettery i settery do rejestrów, pamięci itd.
}

interface Komenda {
void wykonaj(KontekstProcesora kontekst);
}

// Różne implementacje komendy:
class DodajRejestry implements Komenda { ... }
class PrzenieśDoPamięci implements Komenda { ... } // itd.

class MainClass() {
static void main() {
List<Komenda> komendy = new ArrayList<>();
komendy.add(new DodajRejestry(...)); // Dodajemy różne komendy
komendy.add(new PrzenieśDoPamięci(...));
Procesor procesor = new Procesor(komendy);
procesor.start();
}
}

Wydaje mi się, że odpowiedziałem tym kawałkiem kodu na większość Twoich pytań. Co do klasy abstrakcyjnej to z reguły przydaje się do tworzenia klasy bazowej dla implementacji złożonych interfejsów. Inny przykład to gdybyśmy chcieli niektóre komendy wzbogacić o możliwość zrobienia krótkiego sleepa (bo pewne instrukcje mogą się wolniej wykonywać, np. gdy odwołują się do pamięci a my chcemy to zasymulować) to można stworzyć taką klasę abstrakcyjną:

abstract class KomendaZeZwłoką {
private final int zwłoka;

public KomendaZeZwłoką(int zwłoka) {
this.zwłoka = zwłoka;
}

public final void wykonaj(KontekstProcesora kontekst) {
Thread.sleep(zwłoka);
wykonajImpl(kontekst);
}

protected abstract void wykonajImpl(KontekstProcesora kontekst);
}

W tym przypadku użyliśmy klasy abstrakcyjnej w ramach zasady DRY, czyli żeby się nie powtarzać. Oczywiście w rzeczywistości nie ma sensu tylko dla tego jednego sleepa wydzielać klasy abstrakcyjnej, ale jak by to była bardziej złożona logika to jak najbardziej. Najczęściej klasy bazowe abstrakcyjne nazywa się z przedrostkiem Base albo Abstract.

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