Nauka wykorzystania obiektowości

Nauka wykorzystania obiektowości
azalut
  • Rejestracja:około 12 lat
  • Ostatnio:ponad rok
  • Postów:1129
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!

edytowany 1x, ostatnio: flowCRANE
azalut
  • Rejestracja:około 12 lat
  • Ostatnio:ponad rok
  • Postów:1129
0

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

AX
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad 11 lat
  • Postów:33
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.

edytowany 1x, ostatnio: axxxxx
azalut
  • Rejestracja:około 12 lat
  • Ostatnio:ponad rok
  • Postów:1129
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.. :)

AX
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad 11 lat
  • Postów:33
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ń.

AB
  • Rejestracja:prawie 12 lat
  • Ostatnio:prawie 12 lat
  • Postów:2
0

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

azalut
  • Rejestracja:około 12 lat
  • Ostatnio:ponad rok
  • Postów:1129
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:

Kopiuj
setX(0);
setY(0);

czy raczej

Kopiuj
x = 0;
y = 0;

No i w drugim konstruktorze to samo, dac

Kopiuj
setX(x);
setY(x);

czy raczej

Kopiuj
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 ^^

edytowany 2x, ostatnio: azalut
AX
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad 11 lat
  • Postów:33
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):

Kopiuj
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/guava-libraries/wiki/GuavaExplained?tm=6

azalut
  • Rejestracja:około 12 lat
  • Ostatnio:ponad rok
  • Postów:1129
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

Kopiuj
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)

Kopiuj
 
x = 0;
y = 0;

czy moze bardziej

Kopiuj
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

AX
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad 11 lat
  • Postów:33
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:

Kopiuj
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ą:

Kopiuj
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.

azalut
  • Rejestracja:około 12 lat
  • Ostatnio:ponad rok
  • Postów:1129
0

Fju.. procesor, ciężka artyleria :D
Powiedzmy ze chciałbym stworzyć człowieka.. On składa się z elementów tj. psychika, budowa ciała, fizyczność (chodzi mi o to ze sie rusza itp).
Dla wszystkich tych 3 rzeczy musze stworzyc interfejsy tj. Psychika, BudowaCiala i Fizycznosc. Te 3 klasy mam zebrac w jednej klasie abstrakcyjnej "Człowiek", która uogólnia całego człowieka? wlasciwie po co by mi to bylo?
I teraz - każdemu z 3 interfejsow mam podac metody ktore cos robia, np:

Psychika: myslenie(); filozofowanie(); obliczanie(); rozpoznawanieJezykow(); reagowanieNaBodzce();
BudowaCiala: rece(); nogi(); klatkaPiersiowa(); głowa(); brzuch();
Fizycznosc: raczkowanie(); chodzenie(); bieganie(); pływanie(); jazdaNaRowerze();

i tak dalej, dalej..

I mam teraz nowe 3 abstrakcje, czyli.. interfejsy, które opisują ze coś konkretnego mogą zrobic: jeden odpowiada za psychike, drugi za to czy mamy rece, czy nie, czy mamy nogi, czy nie i wielkosc naszego brzucha, a trzeci za nasze powiedzmy umiejetnosci fizyczne. Przez to mozemy używać tego w roznych programach, np: w programie wyboru najpiekniejszej dziewczyny(budowa ciala), w programie wyboru najlepszego koszykarza(budowa ciala, fizycznosc), wyboru najmadrzejszej osoby ze studiow(psychika) itp.?

Dobrze to rozumiem?
W sumie, nawet jeśli dobrze to wymysliłem i tak czuje ze ciezko mi to wdrążyć w życie - np jak to ułożyć w programie ktory robie z dziennikiem :D

uff.. ciężki orzech^^
@axxxxx

azalut
  • Rejestracja:około 12 lat
  • Ostatnio:ponad rok
  • Postów:1129
0

podbije w górę, bo ciekawi mnie odpowiedz ;)
@axxxxx poddałeś się z moją dociekliwościa? :D

AX
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad 11 lat
  • Postów:33
0

Jeśli zamierzasz tworzyć różne implementacje tych interfejsów, to to ma sens. Np. jeśli chcesz żeby dla niepełnosprawnych istniała oddzielna implementacja, przykładowo mając interfejsy Człowiek i Fizyczność, możesz zechcieć stworzyć dwie implementacje tych interfejsów: ZdrowyCzłowiek, ZdrowaFizyczność i NiepełnosprawnyCzłowiek, NiepełnosprawnaFizyczność, która przy tych zapytaniach rzucałaby wyjątki, np. że niepełnosprawny człowiek nie może biegać. Z zewnątrz posługując się interfejsami nie widzimy jak implementacja jest użyta, bo nas to nie obchodzi. Jeśli zrobimy klasę Psychiatra z metodą diagnozuj(Człowiek), to będzie on stawiać diagnozę tylko na podstawie zewnętrznego zachowania tych metod, np. jeśli filozofowanie() zwróci jakieś gadanie o kosmitach, to wie że ma do czynienia ze schizofrenikiem, ale nie obchodzi go czy ten człowiek jest niepełnosprawny, czy np. jest kobietą (jeśli np. zrobimy oddzielnie implementacje CzłowiekKobieta i Mężczyzna). Jeśli nie czynimy takich założeń, tj. zakładamy, że każdy człowiek jest pełnosprawny, to nie trzeba tworzyć żadnych interfejsów dla Człowieka.

Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)