Dziedziczenie w Javie

Podobne dokumenty
Klasy abstrakcyjne, interfejsy i polimorfizm

Dziedziczenie. dr Jarosław Skaruz

Kurs programowania. Wykład 2. Wojciech Macyna. 17 marca 2016

Klasa jest nowym typem danych zdefiniowanym przez użytkownika. Najprostsza klasa jest po prostu strukturą, np

Java - tablice, konstruktory, dziedziczenie i hermetyzacja

Kurs programowania. Wstęp - wykład 0. Wojciech Macyna. 22 lutego 2016

Programowanie obiektowe

Informatyka I. Dziedziczenie. Nadpisanie metod. Klasy abstrakcyjne. Wskaźnik this. Metody i pola statyczne. dr inż. Andrzej Czerepicki

Programowanie obiektowe

Języki i techniki programowania Ćwiczenia 3 Dziedziczenie

Programowanie obiektowe

Wykład 6: Dziedziczenie

Programowanie w Javie 1 Wykład i Ćwiczenia 3 Programowanie obiektowe w Javie cd. Płock, 16 października 2013 r.

Technologie i usługi internetowe cz. 2

JAVA W SUPER EXPRESOWEJ PIGUŁCE

Programowanie obiektowe

Dziedziczenie. Streszczenie Celem wykładu jest omówienie tematyki dziedziczenia klas. Czas wykładu 45 minut.

Aplikacje w środowisku Java

Polimorfizm, metody wirtualne i klasy abstrakcyjne

Dziedziczenie. Tomasz Borzyszkowski

C++ - dziedziczenie. C++ - dziedziczenie. C++ - dziedziczenie. C++ - dziedziczenie. C++ - dziedziczenie C++ - DZIEDZICZENIE.

Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki

TEMAT : KLASY DZIEDZICZENIE

Polimorfizm. dr Jarosław Skaruz

Enkapsulacja, dziedziczenie, polimorfizm

Interfejsy. Programowanie obiektowe. Paweł Rogaliński Instytut Informatyki, Automatyki i Robotyki Politechniki Wrocławskiej

Programowanie Obiektowe i C++

Kurs programowania. Wykład 3. Wojciech Macyna. 22 marca 2019

Klasy abstrakcyjne i interfejsy

10. Programowanie obiektowe w PHP5

MAS dr. Inż. Mariusz Trzaska. Realizacja różnych modeli dziedziczenia w obiektowych językach programowania

Programowanie współbieżne Wykład 8 Podstawy programowania obiektowego. Iwona Kochaoska

Podczas dziedziczenia obiekt klasy pochodnej może być wskazywany przez wskaźnik typu klasy bazowej.

Projektowanie obiektowe. Roman Simiński Polimorfizm

Związek między pojęciami Zasada podstawialności Podklasy muszą realizować kontrakt zawarty przez nadklasy

Typy sparametryzowane

Programowanie obiektowe

Java: kilka brakujących szczegółów i uniwersalna nadklasa Object

Programowanie obiektowe

Interfejsy i klasy wewnętrzne

.NET Klasy, obiekty. ciąg dalszy

Programowanie obiektowe

Programowanie obiektowe - 1.

Programowanie obiektowe w języku

Dziedziczenie i interfejsy

Wstęp do programowania obiektowego. WYKŁAD 3 Dziedziczenie Pola i funkcje statyczne Funkcje zaprzyjaźnione, this

PARADYGMATY PROGRAMOWANIA Wykład 4

Programowanie obiektowe

WSNHiD, Programowanie 2 Lab. 2 Język Java struktura programu, dziedziczenie, abstrakcja, polimorfizm, interfejsy

Dokumentacja do API Javy.

Programowanie obiektowe

Programowanie obiektowe i zdarzeniowe

Programowanie obiektowe

Kurs WWW. Paweł Rajba.

Materiały do zajęć VII

Kompozycja i dziedziczenie klas

Projektowanie obiektowe. Roman Simiński Wzorce projektowe Wybrane wzorce strukturalne

Mechanizm dziedziczenia

Informacje ogólne. Karol Trybulec p-programowanie.pl 1. 2 // cialo klasy. class osoba { string imie; string nazwisko; int wiek; int wzrost;

Programowanie obiektowe

Programowanie w C++ Wykład 13. Katarzyna Grzelak. 4 czerwca K.Grzelak (Wykład 13) Programowanie w C++ 1 / 26

Zad.30. Czy można utworzyć klasę, która implementuje oba interfejsy?

Podstawy Języka Java

Programowanie obiektowe

Java podstawy jęyka. Wykład 2. Klasy abstrakcyjne, Interfejsy, Klasy wewnętrzne, Anonimowe klasy wewnętrzne.

Wzorce Strukturalne. Adapter: opis. Tomasz Borzyszkowski

Programowanie obiektowe Wykład 6. Dariusz Wardowski. dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/14

Programowanie Obiektowe i C++ Marcin Benke

Programowanie obiektowe

2. Klasy cz. 2 - Konstruktor kopiujący. Pola tworzone statycznie i dynamicznie - Funkcje zaprzyjaźnione - Składowe statyczne

Aplikacje Internetowe. Najprostsza aplikacja. Komponenty Javy. Podstawy języka Java

Java: interfejsy i klasy wewnętrzne

1. Które składowe klasa posiada zawsze, niezależnie od tego czy je zdefiniujemy, czy nie?

Kurs programowania. Wykład 13. Wojciech Macyna. 14 czerwiec 2017

Diagramy klas. dr Jarosław Skaruz

Wykład V. Programowanie II - semestr II Kierunek Informatyka. dr inż. Janusz Słupik. Wydział Matematyki Stosowanej Politechniki Śląskiej

Przykład -

Język C++ Programowanie obiektowe

Platformy Programistyczne Wykład z Javy dla zaawansowanych

Wykład 7: Pakiety i Interfejsy

Programowanie 2. Język C++. Wykład 3.

Podstawy Programowania Obiektowego

PHP 5 język obiektowy

Przypomnienie o klasach i obiektach

Wykład 8: klasy cz. 4

Wyjątki. Streszczenie Celem wykładu jest omówienie tematyki wyjątków w Javie. Czas wykładu 45 minut.

Dziedziczenie jednobazowe, poliformizm

Wykład 5 Okna MDI i SDI, dziedziczenie

Programowanie w Javie - wykład 3

Kurs programowania. Wykład 1. Wojciech Macyna. 3 marca 2016

Programowanie obiektowe

Język JAVA podstawy. Wykład 4, część 1. Jacek Rumiński. Politechnika Gdańska, Inżynieria Biomedyczna

Wykład 9: Polimorfizm i klasy wirtualne

Zaawansowane programowanie w C++ (PCP)

Programowanie obiektowe

Programowanie w Javie wykład 7 Klasy c.d. (przeciążanie metod, polimorfizm) Metody i klasy abstrakcyjne Bloki inicjalizacyjne

Pakiety i interfejsy. Tomasz Borzyszkowski

Typy klasowe (klasy) 1. Programowanie obiektowe. 2. Założenia paradygmatu obiektowego:

Projektowanie obiektowe oprogramowania Wykład 4 wzorce projektowe cz.i. wzorce podstawowe i kreacyjne Wiktor Zychla 2015

Transkrypt:

12 kwietnia 2011

Wprowadzenie Klasy modelują pojęcia z dziedziny obliczeń. Pojęcia bywają ze sobą powiązane - chcemy to wyrażać w programach. Można to robić nieskutecznie lub dobrze: Komentarze, Dziedziczenie. Relacja uszczegóławiania (w drugą stronę: uogólniania).

Znaczenie dziedziczenia Dotyczy znaczenia klas a nie ich implementacji. Implementacja ma być ukryta. Zmiany implementacji nie mogą powodować zmian zależności dziedziczenia. Negatywne przykłady: Klasy Punkt i Ułamek, Klasy Lista i Stos.

Znaczenie dziedziczenia cd Jedna z podstawowych własności podejścia obiektowego. Pozwala tworzyć hierarchie. Formy hierarchii. drzewo lub las. DAG lub las DAGóW. Realizacja: podklasa dziedziczy wszystkie atrybuty i metody po nadklasie, także te, które nadklasa sama odziedziczyła, konstruktory się nie dziedziczą (ale to bardziej złożona historia). Terminologia: nadklasa i podklasa, klasa bazowa i klasa pochodna.

Relacje is-a i has-a Dziedziczenie odzwierciedla relację is-a, czyli bycia czymś. Każdy obiekt podklasy jest także obiektem nadklasy. To prosty test na poprawność relacji dziedziczenia. Przykład. Nadklasa Owoc. Podklasy Jabłko i Gruszka. Częsty błąd: mylenie z relacją has-a. Tragicznie zły przykład: Koło dziedziczące po Samochodzie.

Znaczenie dziedziczenia - c.d. Połączenie dwu sprzeczności. Chcemy żeby tworzone oprogramowanie było: Zamknięte (żadnych zmian po zakończeniu testów). Otwarte (używane programy muszą być modyfikowane).

Zasada podstawialności Zawsze można podstawić zamiast obiektu nadklasy obiekt podklasy. Barbara Liskov, Data Abstraction and Hierarchy, SIGPLAN Notices, 23,5, May, 1988. Przykład: tam gdzie oczekujemy Owocu zawsze można podstawić Jabłko. Ale jak to zaimplementować, skoro obiekt podklasy jest zwykle większy od obiektu nadklasy?

Typowe zastosowania dziedziczenia Specjalizowanie pojęć (Prostokąt jako specjalizacja Czworokąta). Specyfikowanie pożądanego interfejsu (klasy abstrakcyjne, interfejsy). Rozszerzanie funkcjonalności (KoloroweOkienko rozszerzające możliwości CzarnoBiałegoOkienka). Nigdy nie używamy do ograniczania funkcjonalności.

Podmienianie metod Podklasy mogą różnie realizować zobowiązania z nadklas. Przykład: metoda śpiewaj w klasach: nadklasa Ptak, podklasy Wrona,Słowik. Można podmieniać (przedefiniowywać, ang. override) metody w podklasach. To niezwykle ważny mechanizm - zapewnia polimorfizm.

Wielodziedziczenie Jednoczesne dziedziczenie po kilku klasach. Np. C++, w Javie właściwie nie ma. Bardzo prosta i przekonująca idea. Niezwykle trudna w implementacji i o niejasnej semantyce. Problem rombu (diamond problem). Diamonds aren t inheritance s best friend Marilyn Monroe, conf. proc. from 1953, (not 100% sure).

Realizacja w Javie Pojedyncze dziedziczenie po klasach. Wielodziedziczenie po interfejsach. Na razie przyjmijmy, że interfejs to bardzo uproszczona klasa. W Javie te dwa rodzaje dziedziczenia są zaznaczane różnymi słowami kluczowymi (extends i implements odpowiednio). Na tym wykładzie: zawsze dziedziczenie i często nadklasa i podklasa w przypadku interfejsów. Każda klasa poza Object dziedziczy po innej (np. po Object).

Przykłady składni dziedziczenia 1 class Pracownik extends Osoba{ 2 // dziedziczenie po klasie 3...} 4 class Samochod implements Pojazd, Towar{ 5 // dziedziczenie po kilku interfesjach 6...} 7 class Chomik extends Ssak 8 implements Puchate, DoGlaskania{ 9 // dziedziczenie po klasie i kilku interfejsach 10...} 11 class Samotnik{ 12 // dziedziczenie po klasie Object 13...}

Java - co klasy dziedziczą Metody. Atrybuty. Także te, które nadklasa sama odziedziczyła.

Przykład z dziedziczeniem 1 class A{ 2 i n t ia =1; 3 void infoa ( ) { 4 System. out. p r i n t l n ( 5 " Jestem infoa ( ) z klasy A \ n " + 6 " wywolano mnie w o b i e k c i e klasy " + 7 this. getclass ( ). getsimplename ( ) + " \ n " + 8 " ia= " +ia ) ; 9 } 10 } Wyrażenie this.getclass().getsimplename() powoduje wypisanie nazwy klasy obiektu, w którym to wyrażenie jest wyliczane.

Przykład z dziedziczeniem cd. 1 class B extends A{ 2 i n t ib =2; 3 void infob ( ) { 4 infoa ( ) ; 5 System. out. p r i n t l n ( 6 " Jestem infob ( ) z klasy B \ n " + 7 " wywolano mnie w o b i e k c i e klasy " + 8 this. getclass ( ). getsimplename ( ) + " \ n " + 9 " ia= " +ia + ", ib= " + ib ) ; 10 } 11 }

Przykład z dziedziczeniem cd. 1 class C extends B{ 2 i n t ic =3; 3 void infoc ( ) { 4 infoa ( ) ; 5 infob ( ) ; 6 System. out. p r i n t l n ( 7 " Jestem infoc ( ) z klasy C\ n " + 8 " wywolano mnie w o b i e k c i e klasy " + 9 this. getclass ( ). getsimplename ( ) + " \ n " + 10 " ia= " +ia + ", ib= " + ib + ", ic= " + ic ) ; 11 } 12 }

Przykład z dziedziczeniem cd. Poniższy fragment 1 C c = new C(); 2 c.infoc(); wypisze...

Przykład z dziedziczeniem cd. Jestem infoa() z klasy A wywolano mnie w obiekcie klasy C ia=1 Jestem infoa() z klasy A wywolano mnie w obiekcie klasy C ia=1 Jestem infob() z klasy B wywolano mnie w obiekcie klasy C ia=1, ib=2 Jestem infoc() z klasy C wywolano mnie w obiekcie klasy C ia=1, ib=2, ic=3

Podsumowanie Klasa C odziedziczyła po swoich przodkach wszystkie atrybuty i metody (podobnie klasa B). Możemy więc myśleć o obiektach klasy C jak o kawałkach tortu składających się z wielu warstw, gdzie każda warstwa odpowiada kolejnej nadklasie...

Komplikujemy Na razie nic szczególnego się nie wydarzyło. Skorzystajmy z zasady podstawialności i zadeklarujemy obiekt klasy C jako obiekt klasy A Dopisujemy więc na końcu naszego programu: 1 A a = new C(); 2 System. out. println("a.ia=" + a.ia + ", c.ia=" + c.ia);

Efekt zmiany Oczywiście na wyjściu naszego programu dodatkowo pojawi się poniższy wiersz: a.ia=1, c.ia=1.

Złośliwa zmiana Wszystkie nazwy atrybutów takie same. Oczywiście normalnie unikamy takiej sytuacji. Ale w praktyce nie ma jak jej zaradzić (nie znamy dalszych nadklas). Co to będzie? (A. Mickiewicz, "Dziady cz. II")

Straszny przykład z dziedziczeniem 1 class A{ 2 i n t i =1; 3 void infoa ( ) { 4 System. out. p r i n t l n ( 5 " Jestem infoa ( ) z klasy A \ n " + 6 " wywolano mnie w o b i e k c i e klasy " + 7 this. getclass ( ). getsimplename ( ) + " \ n " + 8 " i z A= " + i ) ; 9 } 10 }

Straszny przykład z dziedziczeniem cd. 1 class B extends A{ 2 i n t i =2; 3 void infob ( ) { 4 infoa ( ) ; 5 System. out. p r i n t l n ( 6 " Jestem infob ( ) z klasy B \ n " + 7 " wywolano mnie w o b i e k c i e klasy " + 8 this. getclass ( ). getsimplename ( ) + " \ n " + 9 " i z A= " + 10 ( ( A) this ). i + ", i z B= " + i ) ; / / albo super.i 11 } 12 }

Straszny przykład z dziedziczeniem cd. 1 class C extends B{ 2 i n t i =3; 3 void infoc ( ) { 4 infoa ( ) ; 5 infob ( ) ; 6 System. out. p r i n t l n ( 7 " Jestem infoc ( ) z klasy C\ n " + 8 " wywolano mnie w o b i e k c i e klasy " + 9 this. getclass ( ). getsimplename ( ) + " \ n " + 10 " i z A= " + ( ( A) this ). i + ", i z B= " + 11 ( ( B) this ). i + ", i z C= " + i ) ; 12 } 13 }

Straszny przykład z dziedziczeniem cd. Poniższy fragment 1 C c = new C(); 2 c.infoc(); 3 4 A a = new C(); 5 System. out. println("a.i=" + a.i + ", c.i=" + c.i); wypisze...

Straszny przykład z dziedziczeniem cd. Jestem infoa() z klasy A wywolano mnie w obiekcie klasy C i z A=1 Jestem infoa() z klasy A wywolano mnie w obiekcie klasy C i z A=1 Jestem infob() z klasy B wywolano mnie w obiekcie klasy C i z A=1, i z B=2 Jestem infoc() z klasy C wywolano mnie w obiekcie klasy C i z A=1, i z B=2, i z C=3 a.i=1, c.i=3

Wyjaśnienia do przykładu ((A) this) to rzutowanie. Nieeleganckie - rezygnujemy z bezpieczeństwa dawanego przez kompilator i silny system typów. Gdyby się okazało podczas wykonywania, że typy się nie zgadzają, to zostałby zgłoszony wyjątek. Wady dynamicznego sprawdzania typów: spowalnia wykonywanie programu, komunikaty o błędach dostaje niczemu nie winien użytkownik. Zawsze unikajmy rzutowań (o ile się da).

Wyjaśnienia do przykładu cd. Nadal obiekty C mają wszystkie warstwy z nadklas (mimo konfliktu nazw). Dostęp do warstwy z bezpośredniej nadklasy: słowo kluczowe super. Odnosi się do tego obiektu co this, ale traktowanego jak obiekt z nadklasy. super.atrybut oznacza tyle samo co ((Nadklasa) this).atrybut (ale nie dla metod i dlatego dla metod właśnie będzie bardzo cenny). Użyliśmy w programie rzutowania, bo super nie pozwala sięgnąć dwa poziomy wyżej. Ogólna uwaga: poza przykładami ilustrującymi semantykę języka starajmy się nie odwoływać do implementacji innych obiektów, nawet obiektów z nadklas.

Bardzo ważne pytanie Co oznacza a.i? Bardzo ważne pytanie: Czy przy odwoływaniu się do składowych obiektu powinien być brany pod uwagę jego typ statyczny (to jest wynikający z deklaracji w programie), czy typ dynamiczny (czyli faktyczny)? Dla atrybutów decyduje typ statyczny. A dla metod?

Bardzo złośliwa zmiana Wszystkie nazwy metod też takie same. Normalnie będziemy dążyć do takiej sytuacji (choć nie koniecznie w przypadku absolutnie wszystkich metod). Co to będzie, co to będzie? (A. Mickiewicz, "Dziady cz. II")

Bardzo straszny przykład II 1 class A{ 2 i n t i =1; 3 void i n f o ( ) { 4 System. out. p r i n t l n ( 5 " Jestem i n f o ( ) z klasy A \ n " + 6 " wywolano mnie w o b i e k c i e klasy " + 7 this. getclass ( ). getsimplename ( ) + " \ n " + 8 " i z A>> i = " + i ) ; 9 } 10 }

Bardzo straszny przykład II cd. 1 class B extends A{ 2 i n t i =2; 3 void i n f o ( ) { 4 super. i n f o ( ) ; 5 System. out. p r i n t l n ( 6 " Jestem i n f o ( ) z klasy B \ n " + 7 " wywolano mnie w o b i e k c i e klasy " + 8 this. getclass ( ). getsimplename ( ) + " \ n " + 9 " i z A>> i = " + ( (A) this ). i + 10 ", i z B>> i = " + i ) ; / / albo super.i 11 } 12 }

Bardzo straszny przykład II cd. 1 class C extends B{ 2 i n t i =3; 3 void i n f o ( ) { 4 super. i n f o ( ) ; 5 System. out. p r i n t l n ( 6 " Jestem i n f o ( ) z klasy C\ n " + 7 " wywolano mnie w o b i e k c i e klasy " + 8 this. getclass ( ). getsimplename ( ) + " \ n " + 9 " i z A>> i = " + ( ( A) this ). i + 10 ", i z B>> i = " + ( ( B) this ). i + 11 ", i z C>> i = " + i ) ; 12 } 13 }

Bardzo straszny przykład II cd. Poniższy fragment 1 C c = new C(); 2 c.info(); 3 4 A a = new C(); 5 System. out. println("\na.i=" + a.i + 6 ", c.i=" + c.i + "\n"); 7 a.info(); wypisze...

Bardzo straszny przykład II cd. Jestem info() z klasy A wywolano mnie w obiekcie klasy C i z A»i = 1 Jestem info() z klasy B wywolano mnie w obiekcie klasy C i z A»i = 1, i z B»i = 2 Jestem info() z klasy C wywolano mnie w obiekcie klasy C i z A»i = 1, i z B»i = 2, i z C»i = 3 a.i=1, c.i=3

Bardzo straszny przykład II cd. Jestem info() z klasy A wywolano mnie w obiekcie klasy C i z A»i = 1 Jestem info() z klasy B wywolano mnie w obiekcie klasy C i z A»i = 1, i z B»i = 2 Jestem info() z klasy C wywolano mnie w obiekcie klasy C i z A»i = 1, i z B»i = 2, i z C»i = 3

Wyjaśnienia do przykładu Czemu drugie wywołanie metody info dało taki sam efekt jak pierwsze? Zadziałał polimorfizm - obiekt zareagował we właściwy dla siebie sposób. Jak się szuka metod? A jak zapewnił to kompilator? Wygenerował kod, który wybrał właściwą metodę. To jest tanie. To jest bezpieczne zwn typy.

Słowo kluczowe super Znaczenie dla metod: super.metoda(parametry) Metoda zostanie wywołana na rzecz obiektu this, ale wyszukiwanie jej implementacji rozpocznie się od nadklasy klasy, która (tekstowo) zawiera wywołanie metody. Najczęściej używane w (uproszczonym) znaczeniu - wywołaj metodę z nadklasy. Zobaczmy przykład.

super przykład 1 class Osoba { 2 private S t r i n g imie, nazwisko ; 3 / /... 4 @Override 5 public S t r i n g t o S t r i n g ( ) { 6 return " imie = " + imie + ", nazwisko = " + 7 nazwisko ; 8 } 9 }

super przykład 1 class Student extends Osoba { 2 private S t r i n g nrindeksu ; 3 / / Typ String, tak by numer indeksu mógł 4 / / zawierać nie tylko cyfry (np. I-123456) 5 / /... 6 @Override 7 public S t r i n g t o S t r i n g ( ) { 8 return super. t o S t r i n g ( ) + ", nr indeksu = " + 9 nrindeksu ; 10 } 11 }

Komentarz do przykładu Problem: jak sensownie zdefiniować tostring w klasie Student. Chcemy wywołać metodę z Osoby. Umożliwia to super. Kolejny typowy przykład: konstruktor.

super w konstruktorze 1 public Osoba ( S t r i n g imie, S t r i n g nazwisko ) { 2 this. imie = imie ; 3 this. nazwisko = nazwisko ; 4 } 5 6 public Student ( S t r i n g imie, S t r i n g nazwisko, 7 S t r i n g nrindeksu ) { 8 super ( imie, nazwisko ) ; 9 this. nrindeksu = nrindeksu ; 10 }

Ograniczenia wywoływania konstruktora z nadklasy Metodę przez super możemy wywołać wszędzie. Konstruktor tylko i wyłącznie w pierwszej instrukcji. Dlaczego? Bo treść konstruktora ma sens wykonywać dopiero po zainicjowaniu wyższych warstw. A gdy nie napiszemy? Konstruktor bezargumentowy. Ta składnia uniemożliwia przechwycenie wyjątków w konstruktorze nadklasy.

Nieintuicyjne użycie super 1 class StudentStypendysta extends Student { 2 private i n t stypendium ; 3 public StudentStypendysta ( S t r i n g imie, 4 S t r i n g nazwisko, S t r i n g nrindeksu, i n t stypedium ) { 5 super ( imie, nazwisko, nrindeksu ) ; 6 this. stypendium = stypedium ; 7 } 8 @Override 9 public S t r i n g t o S t r i n g ( ) { 10 return super. t o S t r i n g ( ) + ", stypendium = " + 11 stypendium ; 12 } 13 }