Dziedziczenie i słówko extends

Dziedziczenie i słówko extends
RU
  • Rejestracja:ponad 12 lat
  • Ostatnio:około 5 lat
  • Postów:211
0

Od dłuższego czasu mam problem ze zrozumieniem dziedziczenia w javie.
Rozumiem założenia hierarchizacji ale nie wiem jak to ma wyglądać w praktyce.
Napisałem dwie klasy:

Kopiuj
public class Zwierze 
{

	private String imie;
	private String waga;
	
	public String getImie()
	{
		return imie;
	}
	
	void glos()
	{
		System.out.println("odglos");
	}
	
	
} 
Kopiuj
public class KotTest 
{

	public static void main(String[] args) 
	{

		Zwierze zwierze = new Zwierze();
		zwierze.glos();
		System.out.println(zwierze.getImie());
	}

} 
  1. Czy to jest już dziedziczenie, gdzie używam pól i metod w dwóch różnych klasach?
  2. Po co używa się słówka extends, co ono daje?
niezdecydowany
niezdecydowany
  • Rejestracja:ponad 12 lat
  • Ostatnio:około 9 lat
  • Lokalizacja:Bieszczady
0

"Perhaps surprisingly, concurrent programming isn’t so much about threads or
locks, any more than civil engineering is about rivets and I-beams."
SO
  • Rejestracja:ponad 10 lat
  • Ostatnio:12 miesięcy
0

extends "daje" właśnie to dziedziczenie.
A extends B oznacza, że klasa A dziedziczy po klasie B.

To, że masz 2 niepowiązane ze sobą klasy, które maja jakieś metody i pola z dziedziczeniem nie ma nic wspólnego.

RU
  • Rejestracja:ponad 12 lat
  • Ostatnio:około 5 lat
  • Postów:211
0

Ale jeżeli mogę używać pól i metod z innej klasy bez słówka extends to po co mi one skoro nie daje mi ono nowych możliwości?
Tego właśnie nie rozumiem, samo założenie dziedziczenia jest dla mnie jasne ale już wykorzystanie go nie, tym bardziej słówko extends...

edytowany 1x, ostatnio: flowCRANE
Zobacz pozostałe 5 komentarzy
SO
Jak B2 może nie pozwalać Ci na zrozumienie tego tekstu? Przecież B2 to upper-intermediate...
flowCRANE
Zawsze można wspomóc się translatorem, np. tym od Google; Idealnie nie będzie, ale wystarczy do zrozumienia tłumaczonego tekstu;
niezdecydowany
niezdecydowany
następnym razem byda pił zieloną herbatę przed odpowiadaniem na takie wątki :D:D ale muszę przyznać że długo trzymam się bez bana :D:D:D
flowCRANE
Już nie będzie więcej próśb - to już nie pierwszy raz, kiedy naskakujesz na pytacza; Więc przed następnym razem dobrze się zastanów;
niezdecydowany
niezdecydowany
musicie bardziej na luz wrzucić :D kaj wasza ułańska fantazja :D
Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
0

Nie rozumiem pytania. Mam na przykład 3 klasy, z jakąśtam implementacją. Klasa bazowa ma "wspólne" właściwości takie jak ścieżka do pliku, otwieranie pliku i wczytywanie surowych danych. Dziedziczące klasy dodatkowo wykonują parsowanie danych zgodnie ze swoim typem (czyli CSV albo XML).

Kopiuj
class GenericInputFileReader{}
class XMLInputFileReader extends GenericInputFileReader{}
class CSVInputFileReader extends GenericInputFileReader{}

Mam teraz jakiś kod w programie:

Kopiuj
GenericInputFileReader fileReader = getFileReader();
FileContents contents = fileReader.readFile(ścieżka);

Zauważ że w tym kodzie metoda getFileReader() może nam zwrócić obiekt dowolnej z tych 3 klas, ale kodu nie będę musiał nigdzie zmieniać. Co wiecej mogę jutro dopisać sobie nową klasę, która czyta jeszcze inne pliki, a następnie będę musiał tą nową klasę uwzględnić tylko w metodzie getFileReader bo cała reszta kodu pozostaje bez zmian.

Dziedziczenie pozwala mi tu również na nie powtarzanie tego samego kodu 3 razy. Bo otwarcie pliku i wczytanie zawartości w każdej sytuacji wygląda identycznie, jedyna różnica jest taka że "parsowanie" danych wykonuje jakieś transformacje albo po prostu wypluwa treść pliku. Wygodniej więc zamknąć tą "wspólną" logikę w jednej klasie. Szczególnie że może się okazać że coś jeszcze musimy zrobić w trakcie czytania pliku i wtedy musimy to dopisać tylko w 1 miejscu a nie w 3 (albo 50).


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
vpiotr
Przykład nie pasuje do pytania. Autor wątku pytał o dziedziczenie, tutaj mamy do czynienia z polimorfizmem. Dodatkowo w Javie ten akurat przykład raczej zwykle implementuje się przez kompozycję niż dziedziczenie (dekorator): http://stackoverflow.com/questions/6366385/decorator-pattern-for-io
Shalom
@vpiotr polimorfizmu jest tu wspomniany jako szczegół, bo przecież równie dobrze można tworzyć ręcznie obiekty tych 3 klas. Wiem jak wyglądają dekoratory do IO w javie, niemniej wszystko trzeba robić z głową. Jak masz prostą hierarchię dziedziczenia to zamiana tego na delegacje może powodować tylko niepotrzebne problemy dla użytkownika.
N4
  • Rejestracja:około 10 lat
  • Ostatnio:ponad 6 lat
  • Postów:30
0

Zacznijmy od tego co zrobiłeś:

  • utworzyłeś klasę Zwierze,

  • utworzyłeś obiekt o nazwie zwierze (chociaż równie dobrze mógłbyś to nazwać kot, pies itd.),

  • wywołałeś metodę .glos() dla utworzonego obiektu,

  • nie zastosowałeś dziedziczenia.
    Co powinieneś zrobić:

  • utworzyć klasę Zwierze,

  • utworzyć inną klasę np. Kot, Pies, Zolw,

  • przy klasie np. Kot zastosować public class Kot extends Zwierze {...
    Co to daje i po co te dziedziczenie:

  • każde zwierze je prawie tak samo czyli w klasie Zwierze możesz utworzyć metodę typu jedz i w każdej kolejnej klasie typu Kot, Pies nie musisz się powtarzać,

  • zrobiłeś metodę void glos() więc niby jest ok, ale przecież każde zwierze ma inny głos więc powinieneś albo w klasie zwierze zrezygnować z tej metody albo w każdej dziedziczącej klasie ją nadpisać przez co zwierzęta, które maja nadpisaną wersję dadzą swój głos, a tam gdzie nie nadpiszesz będzie do "odglos"

  • acha i na koniec, słowo klucz extends oznacza, że rozszerzasz jakąś klasę o nowe elementy, czyli nowo utworzona klasa (trzymając się przykładów wyżej) Kot to klasa Zwierze + dodatkowe metody + dodatkowe składowe

edytowany 3x, ostatnio: flowCRANE
RU
  • Rejestracja:ponad 12 lat
  • Ostatnio:około 5 lat
  • Postów:211
0
n4lik napisał(a):
  • każde zwierze je prawie tak samo czyli w klasie Zwierze możesz utworzyć metodę typu jedz i w każdej kolejnej klasie typu Kot, Pies nie musisz się powtarzać,

Ale w klasie Kot, Pies, ... mogę użyć metody z klasy Zwierze bez używania słówka extends - tylko tego nie rozumiem, jak pisałem wcześniej rozumiem całe założenie dziedziczenia ale nie rozumiem po co w podklasie mam używać słówka extends skoro nie daje mi ono żadnej nowej funkcjonalności...

SO
rozumiem całe założenie dziedziczenia ale nie rozumiem po co w podklasie mam używać słówka extends przecież to się całkowicie wyklucza...
N4
wpierw sprawdź czy to o czym piszesz rzeczywiście jest takie jak sobie wyobrażasz, koledzy ci podali dobry materiał do zrozumienia a jak nie znasz angielskiego to na necie jest multum, mnóstwo, masa poradników, kursów javy, gdzie wszystko jest opisane w języku polskim tym bardziej, że to o czym piszesz to zwyczajne podstawy
Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
0

Ale w klasie Kot, Pies, ... mogę użyć metody z klasy Zwierze bez używania słówka extends

O RLY? Pics or it didn't happen.


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
Zobacz pozostałe 2 komentarze
niezdecydowany
niezdecydowany
koleś po prostu ma ciśnienie na delegacje, +1 za dobre wzorce projektowe :D:D:D:D
bogdans
Ma sporo wspólnego. Użycie (pierwszy post) metody glos klasy Zwierze w klasie KotTest jest w pełni uzasadnione.
SO
@bogdans, ale ja tam w ogóle nie widzę dziedziczenia.
bogdans
@some_ONE, ja też nie widzę dziedziczenia.
datdata
28.04.2015 14:55: Dziedziczenia ciągle nie widać.
bogdans
Moderator
  • Rejestracja:prawie 17 lat
  • Ostatnio:prawie 5 lat
0

po co w podklasie mam używać słówka extends skoro nie daje mi ono żadnej nowej funkcjonalności

Skoro tak uważasz, to nic nie rozumiesz z dziedziczenia.

Kopiuj
class Zwierze{
     public void dajGlos(){
         System.out.println("");
     }
}
class Osmiornica extends Zwierze{
}
class Test{
     public static void main(String[] args)
     {
          Osmiornica o = new Osmiornica();
          o.dajGlos();
     } 
}

Spróbuj skompilować powyższe klasy po wyrzuceniu słowa extends.


To smutne, że głupcy są tak pewni siebie, a ludzie mądrzy - tak pełni wątpliwości. Bertrand Russell
edytowany 2x, ostatnio: bogdans
H1
  • Rejestracja:około 10 lat
  • Ostatnio:ponad 6 lat
  • Postów:185
0

Troche nie na temat... ale naprawde polecam odchodzić od używania polskich nazw zmiennych w kodzie.

Sarrus
Jak nie na temat, to pisz w komentarzach :P
H1
Przepraszam, biczuję się i wyruszam w drogę do Kalkuty. ;)
bogdans
Chyba do Canossy
RU
  • Rejestracja:ponad 12 lat
  • Ostatnio:około 5 lat
  • Postów:211
0
bogdans napisał(a):

po co w podklasie mam używać słówka extends skoro nie daje mi ono żadnej nowej funkcjonalności

Skoro tak uważasz, to nic nie rozumiesz z dziedziczenia.

Kopiuj
class Zwierze{
     public void dajGlos(){
         System.out.println("");
     }
}
class Osmiornica extends Zwierze{
}
class Test{
     public static void main(String[] args)
     {
          Osmiornica o = new Osmiornica();
          o.dajGlos();
     } 
}

Spróbuj skompilować powyższe klasy po wyrzuceniu słowa extends.

Ale jak zrobię obiekt klasy Zwierze w klasie Osmiornica to działa... czemu tak się dzieje?

SO
  • Rejestracja:ponad 10 lat
  • Ostatnio:12 miesięcy
0
rubesom napisał(a):

Ale jak zrobię obiekt klasy Zwierze w klasie Osmiornica to działa... czemu tak się dzieje?

Bo wtedy ośmiornica sama nie umie dać głosu, ale ma w środku siebie(ble...) inne zwierze, które może dać głos.

Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
1

@rubesom to sie nazywa "delegacja" i generalnie jest bardzo fajną rzeczą. Ale wymaga żeby ten obiekt który tworzysz "wewnątrz" był kompletny. Tzn żeby faktycznie potrafił wykonywać pewną rzecz samodzielnie, a ty tylko dodajesz jakieś operacje przed i po tym wywołaniu. Ale nie zawsze tak jest. Czasem masz pewną wspólną ale niekompletną logikę i nie da sie jej po prostu wywołać.


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
matek3005
  • Rejestracja:prawie 15 lat
  • Ostatnio:prawie 5 lat
  • Postów:358
0

@autor to teraz operując na swoim kodzie stwórz kontener homogeniczny o nazwie schronisko i wrzuć do niego zwięrzta: obiekt klasy testkot i np. dopisz sobie jeszcze w analogiczny sposób testpies i dodaj go do kontenera.

Zasadniczo dziedziczenie niesie ze sobą informację, że dany typ wywodzi się z pewnego typu bazowego przez co może być wykorzystywany przez publiczny interfejs (odziedziczony) w sposób podobny jak obiekty typu bazowego, może również wykorzystywać pewne mechanizmy wewnętrzne typu bazowego niedostępne bezpośrednio przez interfejs publiczny.
Daje Ci to spore możliwości np. traktowania obiektów klas pochodnych w sposób uogólniony - na poziomie klasy bazowej - tak jak w przypadku kontenera schronisko. Zasadniczo nie istotne jest jakie zwierzę tam umieścisz, liczy się to, że jest to zwierzę. Gdyby klasa testkot czy testpies nie dziedziczyły po klasie zwierze, wówczas nie byłoby wiadome jakie rodzaju (typu) one są. To, że nazwiesz klasę kot i skopiujesz w niej interfejs analogiczny jaki jest w klasie zwierze nie czyni kota zwierzęciem do czasu gdy jawnie nie poinformujesz, że kot ma być tym zwierzęciem.

2

mówisz że rozumiesz idee dziedziczenia a w ogóle nic nie rozumiesz
najpierw zrozum co możesz zrobić bez dziedziczenia bo to co robisz nie ma nic wspólnego z dziedziczeniem

może warto żebyś poczytał co to polimorfizm to będzie Ci łatwiej zrozumieć na przykładach
samo dziedziczenie bez polimorfizmu nie daje żadnych specjalnych plusów poza lepszą strukturą kodu i zmniejszeniem jego ilości

ShookTea
  • Rejestracja:około 12 lat
  • Ostatnio:prawie 6 lat
  • Lokalizacja:Wrocław
  • Postów:629
1

Oj, marudzenie. Jakby się nie dało normalnie.

Kopiuj
public class Zwierze {
	public void glos() {
		System.out.println("Glos zwierza");
	}

	public void krzyk() {
		System.out.println("Krzyk zwierza");
	}
}

public class Kot extends Zwierze {
	public void glos() {
		System.out.println("Glos kota");
	}
}

public class Test {
	public static void main(String[] args) {
		Zwierze z = new Zwierze();
		z.glos();
		z.krzyk();
		Kot k = new Kot();
		k.glos();
		k.krzyk();
	}
}

A teraz słuchaj uważnie, co się dzieje w metodzie main:

  1. Tworzymy obiekt klasy Zwierze
  2. Wywołujemy metody glos() i krzyk(), efekty zapewne znasz - są to Glos zwierza i Krzyk zwierza
  3. Tworzymy obiekt klasy Kot, która rozszerza klasę Zwierze
  4. Wywołujemy metodę glos(), która wyświetli w konsoli tekst Glos kota.
  5. Wywołujemy metodę krzyk(), ale, ale! W klasie Kot nie ma metody krzyk()! Ale ponieważ Kot rozszerza Zwierze, jeśli klasa Kot nie ma metody krzyk(), wywołana zostanie metoda krzyk() klasy bazowej, czyli Zwierze. W konsoli wyświetli się więc Krzyk zwierza.

Pamiętaj, że dziedziczenie to relacja "jest" - kot i pies są ssakami, a ssaki i ptaki to zwierzęta, więc możesz stworzyć klasę Zwierze, którą będą rozszerzały klasy Ssak i Ptak, a z kolei klasę Ssak mogą rozszerzać klasy Kot i Pies. W klasie Zwierze umieścisz wszystkie cechy wspólne wszystkich zwierząt, w klasie Ssak te funkcje, które mają ssaki, a w Kot te, które mają koty. Ponieważ Kot nadal jest Ssakiem i Zwierzem, dalej będziesz mógł wywoływać w obiekcie klasy Kot te metody, które zostały zadeklarowane w klasie Zwierze.


edytowany 2x, ostatnio: ShookTea
flowCRANE
Nie "słuchaj uważnie", tylko "czytaj uważnie";
flowCRANE
Nie nie, tylko tak - nie mówisz, więc nikt nie będzie Cię słuchał;
0

Przepraszam, że odpowiadam dopiero teraz ale miałem natłok pracy.
Gwoli wyjaśnienia, nie wiedziałem o czymś takim jak mechanizm delegacji i z tego co widzę nie miałem wiedzy o tym jak powinny być wywoływane obiekty przy zachowaniu dziedziczenia.
Dziękuję wszystkim za cierpliwe wyjaśnienie wielu kwestii, mi najlepiej wyjaśniło wszystko to co napisał @Shalom stąd jego odpowiedź zaakceptuję co by potomni mogli z tego skorzystać.
Dzięki

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)