• Nie Znaleziono Wyników

Dziedziczenie

N/A
N/A
Protected

Academic year: 2021

Share "Dziedziczenie"

Copied!
58
0
0

Pełen tekst

(1)

Wykład 6:

Dziedziczenie

(2)

Dziedziczenie

Jeden z filarów obiektowości.

Budowa jednej klasy na bazie drugiej, przez

dodawanie/przesłanianie jej składowych:

nad-klasa – klasa bazowa

pod-klasa – klasa pochodna od bazowej

(3)

Składnia Dziedziczenia

Składnia:

class pod-klasa extends nad-klasa { // treść klasy

}

Każda pod-klasa posiada tylko jedną nad-klasę:

Java nie umożliwia wielo-dziedziczenia.

(4)

Przykład: Klasa Bazowa

class A { int i; void pokazi() { System.out.println("i: " + i); } }

(5)

Przykład: Klasa Pochodna

class B extends A { int j; void pokazj() { System.out.println("j: " + j); } void suma() { System.out.println("i + j: " + (i + j)); } }

(6)

Przykład: Klasa Testująca

class ProsteDziedziczenie {

public static void main(String args[]) { A a = new A();

B b = new B();

Nad-klasa może być używana samodzielnie:

a.i = 10; a.pokazi();

(7)

Przykład: Klasa Testująca

Pod-klasa ma dostęp do wszystkich publicznych

składowych swojej nad-klasy:

b.i = 7; b.j = 8; b.pokazi(); b.pokazj(); b.suma(); } }

(8)

Dziedziczenie i Składniki Prywatne

Pod-klasa nie ma dostępu do składowych prywatnych

swojej nad-klasy.

Składowa zadeklarowana jako

private

nie jest

dostępna poza klasą w której jest zadeklarowana,

wliczając jej pod-klasy.

(9)

Dziedziczenie i Dostęp, Przykład

class A {

int i;

private int j;

void ustalij(int x, int y) { i = x; j = y; } } class B extends A { int calosc; void suma() { calosc = i + j; // błąd, j niedostępne } }

(10)

Dziedziczenie i Dostęp, Przykład

class DziedziczenieDostep {

public static void main(String args[]) { B b = new B(); b.ustalij(10, 12); b.suma(); System.out.println("Suma to " + b.calosc); } }

(11)

Kolejny Przykład

class Pudelko { double szerokosc; double wysokosc; double glebokosc; Pudelko() { szerokosc = -1; wysokosc = -1; glebokosc = -1; } double objetosc() {

return szerokosc * wysokosc * glebokosc; }

(12)

Kolejny Przykład

class PudelkoPlus extends Pudelko { double ciezar; PudelkoPlus(double s, double c) { szerokosc = s; wysokosc = s; glebokosc = s; ciezar = c; } }

(13)

Kolejny Przykład

class CiezarPudelka {

public static void main(String args[]) {

PudelkoPlus p1 = new PudelkoPlus(10, 5.5); PudelkoPlus p2 = new PudelkoPlus(2, 0.5); double objetosc; objetosc = p1.objetosc(); System.out.println("Pierwsze: " + objetosc); objetosc = p2.objetosc(); System.out.println("Drugie: " + objetosc); } }

(14)

Odwołanie do Obiektu Podklasy

Do zmiennej nad-klasy można przypisać odwołanie do

obiektu dowolnej pod-klasy.

class NadKlasa { ... }

class PodKlasa extends NadKlasa { ... } NadKlasa o1;

PodKlasa o2 = new PodKlasa(); o1 = o2

(15)

Odwołanie Podklasa, Przykład

class DziedziczenieOdwolanie {

public static void main(String args[]) {

PudelkoPlus pp = new PudelkoPlus(10, 0.5); Pudelko p = new Pudelko();

double objetosc; objetosc = pp.objetosc(); System.out.println("Plus: " + objetosc); p = pp; objetosc = p.objetosc(); System.out.println("Pudelko: " + objetosc);

(16)

Odwołanie do Obiektu Podklasy

Typ zmiennej, nie obiekt na który wskazuje ta zmienna,

determinuje osiągalne składowe klasy.

To odwołanie byłoby błędem:

//System.out.println(p.ciezar); }

(17)

Użycie Super jako Konstruktora

Wywołanie konstruktora nad-klasy:

super(lista-parametrow)

Musi być pierwszą instrukcją konstruktora podklasy:

class NadKlasa { ... }

class PodKlasa extends NadKlasa { PodKlasa(...) {

super(...); ... }

... }

(18)

Super jako Konstruktor, Przykład

class Pudelko { double szerokosc; double wysokosc; double glebokosc; Pudelko() {

szerokosc = -1; wysokosc= - 1; glebokosc =-1; } Pudelko(Pudelko p) { szerokosc = p.szerokosc; wysokosc = p.wysokosc; glebokosc = p.glebokosc; } ... }

(19)

Super jako Konstruktor, Przykład

class PudelkoPlus extends Pudelko {

double ciezar; PudelkoPlus() { super(); ciezar = 0; } PudelkoPlus(PudelkoPlus p) { super(p); ciezar = 0; } ... }

(20)

Super jako Konstruktor, Przykład

class SuperKonstruktor {

public static void main(String args[]) { PudelkoPlus pp1 = new PudelkoPlus();

PudelkoPlus pp2 = new PudelkoPlus(10, 5.5); PudelkoPlus pp3 = new PudelkoPlus(pp2);

double objetosc; objetosc = pp1.objetosc(); System.out.println("Pierwsze " + objetosc); objetosc = pp2.objetosc(); System.out.println("Drugie " + objetosc); objetosc = pp3.objetosc(); System.out.println("Trzecie " + objetosc); } }

(21)

Super jako Konstruktor, Przykład

Przesyłamy obiekt pod-klasy:

PudelkoPlus(PudelkoPlus p) { super(p); ciezar = 0;

}

do konstruktora który oczekuje obiekt nad-klasy:

Pudelko(Pudelko p) {

szerokosc = p.szerokosc; wysokosc = p.wysokosc; glebokosc = p.glebokosc; }

(22)

Odwołanie do Nad-Klasy przez Super

Odwołanie do elementu nad-klasy:

super.pole

super.metoda()

Stosowany szczególnie gdy składowe pod-klasy

(23)

Super, Przykład

class A {

int i; }

Przesłonięcie pola w nad-klasie:

class B extends A { int i; B(int a, int b) { super.i = a; i = b; }

(24)

Super, Przykład

void pokaz() { System.out.println("nad-klasa: " + super.i); System.out.println("pod-klasa: " + i); } } class SuperPrzesloniecie {

public static void main(String args[]) { B b = new B(1, 2);

b.pokaz(); }

(25)

Hierarchia Wielo-Poziomowa

class PudelkoPlusPlus extends PudelkoPlus { double koszt;

PudelkoPlusPlus() {

super(); koszt = -1; }

PudelkoPlusPlus(double s, double c, double k) { super(s, c); koszt = k;

}

PudelkoPlusPlus(PudelkoPlusPlus p) { super(p); koszt = p.koszt;

} }

(26)

Hierarchia Wielo-Poziomowa

class Przesylka {

public static void main(String args[]) { PudelkoPlusPlus pp1 = new PudelkoPlusPlus(10,5,15); PudelkoPlusPlus pp2 = new PudelkoPlusPlus(2, 3, 5); double objetosc; objetosc = pp1.objetosc(); System.out.println("Pierwsze " + objetosc); objetosc = pp2.objetosc(); System.out.println("Drugie " + objetosc); } }

(27)

Porządek Wywołań Konstruktorów

W hierarchii klas, najpierw wywołujemy konstruktory

nad-klasy, potem pod-klasy.

Jeżeli

super()

nie jest użyte, wywołuje się domyślny

(28)

Porządek Wywołań Konstruktorów

class A { A() { System.out.println("A"); } } class B extends A { B() { System.out.println("B"); } }

(29)

Porządek Wywołań Konstruktorów

class C extends B { C() { System.out.println("C"); } } class PorzadekKonstruktorow {

public static void main(String args[]) { C c = new C();

} }

(30)

Przesłanianie Metod

Kiedy metoda pod-klasy ma tą samą nazwę i typ jak

metoda nad-klasy, wtedy mówimy że przesłania ją.

Wersja metody dla nad-klasy zostaje ukryta.

(31)

Przesłanianie Metod, Przykład

class A { int i, j; A(int a, int b) { i = a; j = b; } void pokaz() { System.out.println("i i j: " + i + j); } }

(32)

Przesłanianie Metod, Przykład

class B extends A {

int k;

B(int a, int b, int c) { super(a, b); k = c; } void pokaz() { System.out.println("k: " + k); } }

(33)

Przesłanianie Metod, Przykład

class Przeslon {

public static void main(String args[]) { B b = new B(1, 2, 3);

b.pokaz(); }

(34)

Super i Przesłanianie Metod

Wywołanie przesłoniętej metody nad-klasy przez super:

class B extends A { int k;

B(int a, int b, int c) { super(a, b); k = c; } void pokaz() { super.pokaz(); System.out.println("k: " + k); } }

(35)

Przesłanianie czy Przeciążenie?

Przesłanianie metod następuje tylko gdy nazwy i

sygnatury dwóch metod są identyczne.

class B extends A { int k;

B(int a, int b, int c) { super(a, b); k = c;

}

void pokaz(String wiadomosc) {

System.out.println(wiadomosc + k); }

(36)

Przesłanianie czy Przeciążenie?

class Przeladowanie {

public static void main(String args[]) { B b = new B(1, 2, 3);

b.pokaz("Oto k: "); b.pokaz();

} }

(37)

Dynamiczne Wywołanie Metod

Przesłanianie umożliwia dynamiczne wywołanie metod.

Odwołanie do przesłoniętej metody przez zmienną

super-klasy: Java ustala wersję metody na podstawie

faktycznego typu obiektu wskazywanego przez zmienną.

Wykonywany kod decyduje się w czasie rzeczywistym,

nie w czasie kompilacji.

(38)

Dynamiczne Wywołanie, Przykład

class A { void wywolajMnie() { System.out.println("A"); } } class B extends A { void wywolajMnie() { System.out.println("B"); } } class C extends A { void wywolajMnie() { System.out.println("C"); } }

(39)

Dynamiczne Wywołanie, Przykład

class DynamiczneWywolanie {

public static void main(String args[]) { A a = new A(); B b = new B(); C c = new C(); A z; z = a; z.wywolajMnie(); z = b; z.wywolajMnie(); z = c; z.wywolajMnie(); } }

(40)

Polimorfizm

Jeden interfejs, wiele zachowań:

nad-klasa definiuje wspólne metody dla pod-klas

pod-klasa dostarcza specyficzne implementacje dla

niektórych z tych metod

Swoboda definicji własnych metod przez pod-klase, pod

rygorem zachowania interfejsu dla tych metod.

Kombinacja dziedziczenia i przesłaniania: nad-klasa

opisuje format metod realizowanych przez pod-klasę.

(41)

Polimorfizm, Przykład

class Figura { double d1; double d2; Figura(double a, double b) { d1 = a; d2 = b; } double powierzchnia() { System.out.println("Niezdefiniowana"); return 0; } }

(42)

Polimorfizm, Przykład

class Prostokat extends Figura { Prostokat(double a, double b) { super(a, b); } double powierzchnia() { System.out.println("Prostokat"); return d1 * d2; } }

(43)

Polimorfizm, Przykład

class Trojkat extends Figura {

Trojkat(double a, double b) { super(a, b); } double powierzchnia() { System.out.println("Trojkat"); return d1 * d2 / 2; } }

(44)

Polimorfizm, Przykład

class Polimorfizm {

public static void main(String args[]) { Figura f = new Figura(10, 10);

Prostokat p = new Prostokat(9, 5); Trojkat t = new Trojkat(10, 8);

Figura r; r = p;System.out.println(r.powierzchnia()); r = t;System.out.println(r.powierzchnia()); r = f;System.out.println(r.powierzchnia()); } }

(45)

Metody Abstrakcyjne

Metoda dla której nie istnieje implementacja.

abstract typ nazwa(lista-parametrow);

Metody:

konkretne - mogą być przesłonięte przez pod-klasy

abstrakcyjne - muszą zostać przesłonięte

Nie wolno definiować abstrakcyjnych konstruktorów,

ani metod statycznych.

(46)

Klasy Abstrakcyjne

Klasa która posiada metody abstrakcyjne musi sama

być deklarowana jako abstrakcyjna.

abstract class { ... }

Klasa abstrakcyjna nie posiada obiektów; nie wolno

używać

new

na takiej klasie.

Pod-klasa klasy abstrakcyjnej:

implementuje wszystkie metody abstrakcyjne albo

jest sama deklarowana jako abstrakcyjna.

(47)

Klasy Abstrakcyjne

abstract class A {

abstract void wywolajMnie(); void wywolajMnieTez() { System.out.println("metoda konkretna"); } } class B extends A { void wywolajMnie() { System.out.print("implementacja metody "); System.out.println("abstrakcyjnej"); } }

(48)

Klasy Abstrakcyjne

class KlasaAbstrakcyjna {

public static void main(String args[]) { B b = new B();

b.wywolajMnie();

b.wywolajMnieTez(); }

(49)

Klasy Abstrakcyjne, Przykład

Abstrakcyjna klasa

Figura

posiada abstrakcyjną

metodę

powierzchnia

:

abstract class Figura { double d1; double d2; Figura(double a, double b) { d1 = a; d2 = b; }

abstract double powierzchnia(); }

(50)

Klasy Abstrakcyjne, Przykład

Pod-klasa

Prostokat

dostarcza konkretną

implementację metody

powierzchnia

:

class Prostokat extends Figura { Prostokat(double a, double b) { super(a, b); } double powierzchnia() { System.out.println("Prostokat"); return d1 * d2; } }

(51)

Klasy Abstrakcyjne, Przykład

Pod-klasa

Trojkat

dostarcza konkretną

implementację metody

powierzchnia

:

class Trojkat extends Figura { Trojkat(double a, double b) { super(a, b); } double powierzchnia() { System.out.println("Trojkat"); return d1 * d2 / 2; } }

(52)

Klasy Abstrakcyjne, Przykład

class AbstrakcyjnaFigura {

public static void main(String args[]) {

Nie wolno tworzyć obiektów klasy abstrakcyjnej:

Figura f = new Figura(10, 10);

Prostokat p = new Prostokat(9, 5); Trojkat t = new Trojkat(10, 8);

Wolno tworzyć odwołania do klasy abstrakcyjnej:

Figura r;

r=p;System.out.println(r.powierzchnia()); r=t;System.out.println(r.powierzchnia()); }

(53)

Final Zapobiega Przesłanianiu

Metodę deklarowaną jako

final

w nad-klasie nie

wolno przesłaniać w pod-klasie:

class A {

final void meth() {

System.out.println("Metoda final"); } } class B extends A { void meth() { System.out.println("Nielegalne!"); } }

(54)

Final Zapobiega Przesłanianiu

Dwa rodzaje wywołań metod:

wczesne – wywołanie ustalone w trakcie kompilacji

późne – wywołanie ustalane w trakcie wykonania

Jako że metoda

final

nie może zostać przesłonięta,

podlega wczesnemu wywołaniu.

(55)

Final Zapobiega Dziedziczeniu

Klasa deklarowana jako

final

nie posiada potomków,

nie wolno po niej dziedziczyć.

final class A { ... }

Ta klasa jest nielegalna:

(56)

Klasa Object

Klasa

Object

jest nad-klasą wszystkich klas w Javie.

Zmienna typu

Object

może odwoływać się do obiektu

dowolnej klasy, jak też do dowolnej tablicy.

Metody deklarowane przez

Object:

Object clone()

tworzy obiekt który jest

idealną kopią danego obiektu

boolean equals(Object object)

ustala czy

(57)

Klasa Object

void finalize()

wywołana zanim nieużywany

obiekt jest niszczony przez śmieciarkę

final Class getClass()

uzyskuje dostęp do

klasy obiektu w trakcie wykonania

int hashCode()

zwraca kod haszujący dla

danego obiektu

final void notify()

podejmuje ponowne

wykonanie wątku który czeka na danym obiekcie

final void notifyAll()

podejmuje wykonanie

(58)

Klasa Object

String toString()

zwraca ciąg znaków który

opisuje dany obiekt, jest wywoływany przez

print

final void wait()

czeka na inny wątek

final void wait(long mili)

Obraz

Figura f = new Figura(10, 10);

Cytaty

Powiązane dokumenty

Stosowanie klas abstrakcyjnych jest konieczne, jeżeli ma istnieć możliwość operowania w tym samym kontekście na obiektach różnych klas, które nie mają naturalnej

// faktycznie tworzony jest obiekt klasy RECTANGLE // wszystkie inne jawne metody klasy są dostępne jako // odziedziczone z klasy

Ale skoro każdy podzbiór zbioru liczb naturalnych ma swój unikalny kod w postaci nieskończonego ciągu zer i jedynek (oraz każdy ciąg zer i jedynek odpowiada pewnemu podzbiorowi

Pojawi się zatem mechanizm polimorfizmu - czyli metoda Rysuj, w zależności od obiektu, na którymjest wykonywana,.. sporządzi inny

Jej 3 klasy potomne, natomiast, będą posiadały metodę Narysuj() (z atrybutem Overrides) rysującą, w uproszczeniu, modyfikację stopnia, czyli pręt, gwint lub dla klasy

W Javie - do wersji 7 włącznie - interfejs to klasa czysto abstrakcyjna, czyli taka, w której wszystkie metody są traktowane jako abstrakcyjne.. W wersji 8 wprowadzono jednak

produktów, ich stworzenie jest zadaniem konkretnych fabryk – najczęściej robi się to definiując factory method dla każdego produktu, co wymaga nowej fabryki dla każdej

2) Z papieru do pieczenia zgniećcie kulę. Taki papier na namięka ale można go "ubrudzić" wodną farbą.. 3) Rozwodnioną farbę można rozlać