Figura[]

Transkrypt

Figura[]
Podstawy programowania obiektowego
Technologie internetowe
Wykład 7
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Program wykładu
●
Dziedziczenie
●
Wywołania konstruktorów w dziedziczeniu
●
Hermetyzacja w dziedziczeniu
●
Dziedziczenie typu, rzutowanie w górę i w dół
●
Mechanizm RTTI
●
Nadpisywanie pól
●
Nadpisywanie metod – polimorfizm
●
Klasy i metody finalne
●
Klasy i metody abstrakcyjne
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Dziedziczenie
●
●
●
technika konstruowania nowych klas z wykorzystaniem klas
już istniejących (jak kompozycja !)
opisuje relację między 2 klasami:
„... jest szególnym przypadkiem ...”, „... jest rodzajem ...”
rzadziej stosowana i trudniejsza technika od kompozycji
Komputer
Figura
Samochód
Trójkąt
Notebook
Ciężarówka
Wyścigówka
Czworokąt
Prostokąt
Kwadrat
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Dziedziczenie w kodzie
class Figura { ... }
Klasa bazowa
Nadklasa
Klasa dziedziczona
Base class
Super class
class Trojkat extends Figura { ... }
class Czworokat extends Figura { ... }
class Prostokat extends Czworokat { ... }
Figura
class Kwadrat extends Prostokat { ... }
Klasa dziedzicząca
Podklasa
Derived class
Base class
Subclass
Trójkąt
Czworokąt
Prostokąt
Kwadrat
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Dziedziczenie jako zawieranie się podzbiorów
●
każdy kwadrat jest prostokątem
●
wśród prostokątów niektóre są szczególne: kwadraty
●
kwadrat zatem dziedziczy z prostokąta
FIGURY
Figura
CZWOROKĄTY
TROJKĄTY
PROSTOKĄTY
Trójkąt
Czworokąt
KWADRATY
Prostokąt
Kwadrat
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Konsekwencje dziedziczenia
●
klasa dziedzicząca przejmuje kod z klasy bazowej:
class Figura {
Punkt srodek;
public void przesun(int dx, int dy)
{ srodek.przesun (dx, dy);}
}
class Kolo extends Figura { int r; }
...
Kolo k = new Kolo();
k.srodek = new Punkt(5,5);
k.r = 3;
k.przesun(1,0);
●
korzyści:
●
mniej kodowania
●
propagowanie zmian
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Konstruktory w dziedziczeniu
●
Konstruktory nie dziedziczą się !!!
class Figura {
Punkt srodek;
public Figura(Punkt s) { srodek = new Punkt(s); }
}
class Kolo extends Figura {
int r;
public Kolo(Punkt s, int rr)
{ srodek=new Punkt(s); r=rr; }
}
...
Figura f=new Figura( new Punkt(0,0));
Kolo k = new Kolo ( new Punkt(10,10), 5);
●
ale to się nie skompiluje
●
dlaczego ?
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
→
Obiekty klas dziedziczących
●
tworzą się po kolei aż 4 obiekty (5) !!!
Kwadrat k = new Kwadrat(new Punkt(1,1), 10));
1
2
Figura
środek
new Figura(...)
→
3
Czworokąt
Figura
Prostokąt
Czworokąt
Figura
Kwadrat
Prostokąt
Czworokąt
Figura
środek
środek
środek
new Czworokat(...) →
new Prostokat(...) →
new Kwadrat(...)
●
a każdy obiekt to wywołanie konstruktora
●
który potrzebuje parametrów
●
który konstruktor ma się wywołać (przeciążanie) ?
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
4
Porządek wywołania konstruktorów
●
●
każdy konstruktor klasy dziedziczącej musi wskazać konkretny
konstruktor klasy bazowej, który wywoła się przed nim:
●
nazwa klasy bazowej zastępowana jest słowem super
●
konstruktor wybiera się podając jego parametry (przeciążanie!)
●
wskazanie to musi być pierwszą instrukcją konstruktora
jeśli tego nie zrobi kompilator wskaże konstruktor domyślny:
class B extends A {
public B() {}
}
●
→ public B() { super(); }
tu: zanim wywoła się domyślny konstruktor klasy B
przed nim wywoła się domyślny konstruktor klasy A
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Przykład wywołań konstruktorów
class A {
public A() { System.out.println("A.A()"); }
public A(int i) { System.out.println("A.A(int)"); }
}
class B extends A {
public B() {super(0);System.out.println("B.B()"); }
public B(int i) {System.out.println("B.B(int)"); }
}
class C extends B {
public C() { System.out.println("C.C()"); }
public C(int i) {super(i);System.out.println("C.C(int)");}
}
...
new C();
→ A.A(int) B.B() C.C()
new C(1);
→ A.A() B.B(int) C.C(int)
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
A.A()
A.A(int)
B.B()
B.B(int)
C.C()
C.C(int)
Konstruktory jeszcze raz
●
brakuje konstruktora domyślnego Figury
class Figura {
Punkt srodek;
public Figura(Punkt s) { srodek = new Punkt(s); }
}
class Kolo extends Figura {
int r;
public Kolo(Punkt s, int rr)
{ super(); srodek=new Punkt(s); r=rr; }
}
to wstawia kompilator
...
Figura f=new Figura( new Punkt(0,0));
Kolo k = new Kolo ( new Punkt(10,10), 5);
●
lub wskazania innego konstruktora
●
i jego parametrów
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Konstruktory jeszcze raz
●
wskazanie właściwego konstruktora
class Figura {
Punkt srodek;
public Figura(Punkt s) { srodek = new Punkt(s); }
}
class Kolo extends Figura {
int r;
public Kolo(Punkt s, int rr)
{ super(s); srodek=new Punkt(s); r=rr; }
}
...
Figura f=new Figura( new Punkt(0,0));
Kolo k = new Kolo ( new Punkt(10,10), 5);
●
przy okazji inicjacja odziedziczonego pola
●
który powinien być ... prywatny ?
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Hermetyzacja w dziedziczeniu
●
czy prywatne pola/metody się dziedziczą ?
class Figura {
private Punkt srodek;
public Figura(Punkt s) { srodek = new Punkt(s); }
}
class Kolo extends Figura {
int r;
public Kolo(Punkt s, int rr) { super(s); r=rr; }
public void przesun(int dx, int dy) {
srodek.przesun(dx, dy); BŁĄD HERMETYZACJI
}
●
dziedziczą się, ale są niedostępne !`
●
metoda 'przesun' powinna być zdefiniowana w Figurze
●
albo należy użyć nowego poziomu ochrony ...
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Poziom ochrony 'protected'
●
pośredni poziom między 'public' a 'private'
●
publiczny dla rodziny (w drzewie dziedziczenia)
●
prywatny dla innych (obcych) klas
class Figura {
protected Punkt srodek;
public Figura(Punkt s) { srodek = new Punkt(s); }
}
class Kolo extends Figura {
int r;
public Kolo(Punkt s, int rr) { super(s); r=rr; }
public void przesun(int dx, int dy) {
srodek.przesun(dx, dy); OK
`
}
...
Figura f=new Figura( new Punkt(0,0));
f.srodek=null; BŁĄD
Kolo k = new Kolo ( new Punkt(10,10), 5);
System.out.println(k.srodek); BŁĄD
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Dziedziczenie
●
●
nie dziedziczy się:
●
konstruktorów
●
(destruktorów, operatora= w C++)
dziedziczy się:
●
pola
●
metody
●
typ
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
`
Po co typ ?
●
kompilator pilnuje zgodności typów:
int i;
float f;
i = f; BŁĄD
void f(int a) {...}
f(”abc”); BŁĄD
Samochód s = new Komputer();
●
BŁĄD
ale czasami można go „oszukać” → rzutowanie (casting)
`
i = (int)f; OK
Samochód s = (Samochód)new Komputer();
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
BŁĄD
Dziedziczenie typu
●
●
klasa Kwadrat ma 4 typy (5):
●
Figura
●
Czworokat
●
Prostokat
●
Kwadrat
Czworokąt
więc kompilator dopuści podstawienie:
Figura f = new Kwadrat(...);
●
Figura
rzutowanie w górę !!! (upcasting)
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
`
Prostokąt
Kwadrat
Rzutowanie w górę
Figura[] figury = new Figura[100];
figura[0] = new Kwadrat(...);
figura[1] = new Prostokat(...);
figura[2] = new Trojkat(...);
●
rzutowanie to zachodzi tylko w dziedziczeniu
●
zawsze jest możliwe i bezpieczne
`
●
upraszcza przechowywanie obiektów z 1 rodziny
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Klasa Object
●
●
dlaczego Kwadrat ma 5 typów ?
każda klasa w Javie dziedziczy z klasy 'Object'
(bezpośrednio lub pośrednio)
class Figura {... }
→ class Figura extends Object {...}
●
pojedyncze drzewo dziedziczenia
●
składowe klasy Object:
●
public String toString();
●
public boolean equals(Object o); `
●
●
metody związane z wątkami
referencja typu 'Object'
Object o = new ...
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Object
Figura
Czworokąt
Prostokąt
Kwadrat
Utrata dostępu do informacji
Figura[] figury;
for (Figura f: figury) f.przesun(1, 0);
ale
Figura f = new Kolo(new Punkt(1,2), 10);
System.out.println(f.getR());
●
skąd wiadomo że 'f' to Koło ?
Figura f;
if (random.nextInt(2)%2 == 0)
f = new Kolo(new Punkt(1,2), 10);
else
f = new Prostokat(new Punkt(1,2), 4, 6);
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Utrata dostępu do informacji
●
●
●
●
obiekt Koło cały czas jest w pamięci – nie zmienia typu !!!
(obiekt raz stworzony jako Koło zawsze będzie już Kołem)
rzutowanie w górę zmienia tylko
sposób patrzenia na obiekt
kompilator mając referencję 'Figura f'
nie zna rzeczywistego typu obiektu
na który ona wskazuje
wie, że ten obiekt to jakaś Figura
i ma metodę 'przesun(int,int)'
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
f
- srodek:Punkt
+przesun(int,int)
- r: int
+ getR(): int
Rzutowanie w dół (downcasting)
●
●
rzutowanie z typu bazowego
na typ pochodny
ale to zły przykład:
Object
Figura
Kolo k = (Kolo)new Figura(...);
●
dobry przykład:
Figura f = new Kolo(...);
Kolo k = (Kolo)f;
●
poprawne rzutowanie w dół może nastąpić tylko
po wcześniejszym rzutowaniu w górę
●
odzyskanie utraconego dostępu do informacji
●
rzutowanie w dół jest ryzykowne
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Czworokąt
Prostokąt
Kwadrat
Mechanizm RTTI
●
●
f
identyfikacja typu w czasie wykonania programu
(Run-Time Type Identification)
umożliwia świadome i poprawne rzutowanie w dół
if (f instanceof Kolo) {
Kolo k = (Kolo)f;
System.out.println(k.getR());
●
●
operator 'instanceof' bada, czy 'f ' ma typ 'Kolo'
jego bezpośrednie używanie (nadużywanie) jest
uważane za mało eleganckie
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
?
Wykorzystanie 'instanceof'
●
policzenie figur w tablicy
Figura[] figury={ new Kwadrat(...),
new Prostokat(...), new Czworokat(...)}
int lczw, lprost, lkw=0;
for (Figura f: figury) {
if (f instanceof Kwadrat) ++ lkw;
if (f instanceof Prostokat) ++ lprost;
if (f instanceof Czworokat) ++ lczw;
}
System.out.println(”Kwadraty: ”+lkw);
System.out.println(”Prostokąty: ”+lprost);
System.out.println(”Czworokąty: ”+lczw);
●
wynik: 1 2 3 !!!
●
przecież każdy prostokąt jest też czworokątem !!!
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Wykorzystanie 'instanceof'
●
alternatywne policzenie figur w tablicy
...
if (f instanceof Kwadrat) ++ lkw;
else if (f instanceof Prostokat) ++ lprost;
else if (f instanceof Czworokat) ++ lczw;
...
●
lub:
if (f instanceof Kwadrat) ++ lkw;
if ( f instanceof Prostokat &&
! f instanceof Kwadrat) ++ lprost;
if ( f instanceof Czworokat &&
! f instanceof Prostokat) ++ lczw;
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Object
Figura
Czworokąt
Prostokąt
Kwadrat
Nadpisywanie składowych
●
w dziedziczeniu składowe dziedziczą się
●
ale dopuszczalne jest ich nadpisywanie:
class A { int x; }
class B extends A { int x; }
●
●
w takiej sytuacji obiekt B
ma 2 zmienne 'x' !!!
w przypadku pól
to zwykle pomyłka
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
B
A
x 3
x 5
Nadpisywanie pól
class A {
int x;
}
class B extends A {
int x;
}
class C extends B {
int x;
public void showAll() {
System.out.println("A.x="+A.x+",B.x="+super.x+",C.x="+x);
}
}
C
B
A
C c = new C();
c.x = 30;
x 10
c.showAll();
((B)c).x = 20;
((A)c).x = 10;
x 20
c.ShowAll();
●
ważny jest typ referencji !!!
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
x 30
Nadpisywanie metod
●
●
●
●
●
w zasadzie nadpisywanie metod działa tak samo
ale w Javie jest specjalny mechanizm,
który komplikuje sprawę: POLIMORFIZM
przy wywołaniu metod nie jest ważny typ
referencji (jak w przypadku pól)
ważny jest typ obiekty
który się za nią ukrywa
f
?
metody wywoływane w ten sposób nazywane są
metodami/funkcjami wirtualnymi
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Nadpisywanie a przeciążanie
(overriding vs overloading)
●
to nie jest nadpisywanie tylko przeciążanie:
class A { String f() { return ”A.f”;} }
class B extends A { String f(int a) { return ”B.f”;} }
class C extends B { String f(char c) { return ”C.f”;} }
C
B
A
C c = new C();
System.out.println(c.f());
System.out.println(c.f(0));
System.out.println(c.f('a'));
●
nadpisywanie:
+ A.f()
+ B.f(int)
+ C.f(char)
C
B
A
class A { String f() { return ”A.f”;} }
class B extends A { String f() { return ”B.f”;} }
class C extends B { String f() { return ”C.f”;} }
System.out.println(c.f()); ???
+ A.f()
+ B.f()
+ C.f()
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Wiązanie metod (binding)
class A {
public String
}
class B extends
public String
}
class C extends
public String
}
f() { return ”A.f”;}
A {
f() { return ”B.f”;}
B {
f() { return ”C.f”;}
C
B
A
+ A.f(): String
0x02ca4
+ B.f(): String
+ C.f(): String
0x02cc4
0x02ce4
A a = new C();
System.out.println(a.f());
●
obiekt klasy C ma 3 metody 'f()'
●
każda ma inny adres w pamięci kodu
●
kompilator musi wskazać, którą metodę wywołać
●
skompilować znaczy przetłumaczyć na asembler:
a.f(); → jump 0x02cc4 ? wiązanie metody
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Wiązanie wczesne i późne
●
jeśli kompilator faktycznie wiąże metodę →
wiązanie wczesne a.f(); → jump 0x02ca4
●
jaką metodę wybiera ?
–
●
z tej klasy, jakiego typu jest referencja 'a' (A)
jeśli kompilator nie wiąże kodu →
wiązanie późne
a.f(); → jump _______
●
kiedy wykona się te wiązanie ?
–
●
w czasie wykonania programu (run-time)
jaka metoda zostanie wybrana ?
–
z tej klasy, jakiego typu jest obiekt
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Funkcje/Metody wirtualne
●
metody wiązane wcześnie – zwykłe metody
●
metody wiązane późno – metody wirtualne
●
mechanizm późnego wiązania metod –
polimorfizm
●
w Javie (prawie) wszystkie metody są wirtualne
●
nie trzeba ich oznaczać (jak w C++ 'virtual')
●
metody wirtualne mogą nieznacznie spowalniać
wykonanie programu
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Figura
Typowe użycie f. wirtualnych
Trójkąt
Czworokąt
class Figura {
public String opis(){return ”Jestem Figurą”;}}
class Trojkat extends Figura {
public String opis(){return ”Jestem Trójkątem”;}}
class Czworokat extends Figura {
public String opis(){return ”Jestem Czworokątem”;}}
Prostokąt
Kwadrat
class Prostokat extends Czworokat {
public String opis(){return ”Jestem Prostokątem”;}}
class Kwadrat extends Prostokat {
public String opis(){return ”Jestem Kwadratem”;}}
...
Figura f=new ???
System.out.println(f.opis());
...
System.out.println(xxx.opis());
xxx
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
???
Metody niewirtualne
●
w Javie wyjątkami (zwykłymi metodami) są metody:
●
finalne
●
statyczne
●
prywatne
class A {
private String f() { return ”A.f”; }
public String g() { return ”A.g;” }
public String call() { return f()+” ”+g(); }
}
class B extends A {
private String f() { return ”B.f”; }
public String g() { return ”B.g;” }
}
...
A a = new B();
System.out.println(a.call());
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Metody niewirtualne
●
w Javie wyjątkami (zwykłymi metodami) są metody:
●
finalne
●
statyczne
●
prywatne
class A {
wywołanie wirtualne
private String f() { return ”A.f”; }
public String g() { return ”A.g;” }
public String call() { return f()+” ”+g(); }
}
wywołanie niewirtualne
class B extends A {
private String f() { return ”B.f”; }
public String g() { return ”B.g;” }
}
...
A a = new B();
System.out.println(a.call());
→ A.f B.g
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Jeszcze metody niewirtualne
class A {
private String f() { return ”A.f”; }
public String g() { return ”A.g;” }
}
class B extends A {
private String f() { return ”B.f”; }
public String g() { return ”B.g;” }
public String call() { return f()+” ”+g(); }
}
...
A a = new B();
System.out.println(a.call());
→ ???
●
metoda 'call' w klasie B
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Jeszcze metody niewirtualne
class A {
private String f() { return ”A.f”; }
public String g() { return ”A.g;” }
}
class B extends A {
wywołanie wirtualne
private String f() { return ”B.f”; }
public String g() { return ”B.g;” }
public String call() { return this.f()+” ”+this.g(); }
}
...
wywołanie niewirtualne
A a = new B();
System.out.println(a.call());
→ B.f B.g
●
'this' w kodzie klasy A jest typu A
●
'this' w kodzie klasy B jest typu B
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Poziom kodu
class A {
protected int x = 10;
public int getAx() { return x; }
}
class B extends A {
x 10
protected int x = 20;
public int getBx() { return x; }
}
x 20
class C extends B {
protected int x = 30;
public int getCx() { return x; }
x 30
}
...
C c= new C();
System.out.println(””+c.getAx()+c.getBx()+c.getCx());
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
C
B
A
→
Poziom kodu
A
class A {
typu A
#x
protected int x = 10;
+getAx()
public int getAx() { return this.x; }
}
class B extends A {
typu B
B
protected int x = 20;
#x
public int getBx() { return this.x; }
+getBx()
}
class C extends B {
typu C
protected int x = 30;
C
public int getCx() { return this.x; }
#x
}
+getCx()
...
C c= new C();
System.out.println(””+c.getAx()+c.getBx()+c.getCx()); → 10 20 30
●
kod sięga do pola ze swojemu poziomu
●
potem do pól odziedziczonych (do góry)
●
nigdy nie sięga w dół (do klas dziedziczących)
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Klasy i metody finalne
●
z klasy finalnej nie można dziedziczyć
finall class Ostateczna { ... }
class Nowa extends Ostateczna { ... }
●
●
metody finalnej nie można nadpisać
jest też metodą niewirtualną (m.in. szybciej się
wykonuje – wiązanie wczesne)
class Prostokat {
protected double a, b;
public final double pole() { return a*b; }
public Prostokat(double aa, double bb) { a=aa; b=bb; }
}
class Kwadrat extends Prostokat {
public Kwadrat(int a) { super(a, a); }
public double pole() { return ... }
}
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Klasy abstrakcyjne
●
z klasy abstrakcyjne nie można utworzyć obiektu
abstract class Figura { ... }
new Figura(...);
●
klasa abstrakcyjna służy tylko do dziedziczenia
class Kolo extends Figura { ... }
class Trojkat extends Figura { ... }
●
ale można tworzyć referencje typu abstrakcyjnego
Figura f = null;
Figura[] figury = new Figura[100];
f=new Kolo(...);
figury[0] = new Trojkat(...);
●
●
klasa abstrakcyjna to zwykła klasa:
może mieć pola, metody, konstruktory
klasa abstrakcyjna ma 1 przywilej:
tylko ona może posiadać metody abstrakcyjne → ...
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Metody abstrakcyjne
●
metoda abstrakcyjna to metoda niedokończona,
zawiera tylko nagłówek
abstract class Figura {
protected Punkt srodek;
public abstract double pole();
}
●
●
używana kiedy jej definicja nie miałaby sensu
(jak policzyć pole jakiejś nieokreślonej figury ?)
klasa która dziedziczy z klasy abstrakcyjnej metodę
abstrakcyjną musi ją zdefiniować do końca
class Kolo extends Figura {
protected double r;
public double pole() { return Math.PI*r*r; }
}
●
metoda abstrakcyjna nigdy nie będzie wywoływana:
jest wirtualna a nigdy nie stworzy się obiekt klasy Figura
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Po co metody abstrakcyjne ?
●
kompilator ma wywołanie:
Figura f = ...
f.pole();
●
●
musi sprawdzić, czy w klasie Figura metoda 'pole()'
nie jest np.: statyczna, finalna, prywatna → niewirtualna
metoda abstrakcyjna narzuca na klasy dziedziczące
obowiązek posiadania kompletnej metody 'pole()'
(jeśli same nie chcą być abstrakcyjne):
abstract class Figura2D extends Figura { }
●
metoda abstrakcyjna definiuje interfejs hierarchii klas
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Wywoływanie metod zastępowanych
●
konstruktor klasy dziedziczącej woła konstruktor klasy bazowej
●
nowa metoda wirtualna całkowicie zastępuje przesłanianą metodę
●
metoda zastępujące może po raz ostatni wywołać metodę
zastępowaną
class Figura {
public String opis() {return ” Jestem Figurą”;}
}
class Kolo extends Figura {
public String opis(){return super.opis()+” i Kołem”;}
}
...
Figura f=new Koło();
System.out.println(f.opis()); → Jestem Figurą i Kołem
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Metoda 'public String toString()'
●
metoda zdefiniowana w klasie 'Object'
●
oryginalna definicja wypisuje rzeczywistą nazwę klasy i nr referencji
●
zwraca tekstową reprezentację obiektu
●
często wykorzystywana
class Punkt extends Object { private x, y; }
...
Punkt p=new Punkt (1,2);
System.out.print(p);<==>System.out.print(p.toString());
→ Punkt@0x23cd
●
można ją nadpisać i w nowej metodzie wywołać oryginalną definicję:
class Punkt extends Object { private x, y;
public String toString()
{ return super.toString+”(x:”+x+”,y:”+y+”)”; }
}
System.out.print(p);→ Punkt@0x23cd(x:1,y:2)
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
Hermetyzacja a funkcje wirtualne
●
przy nadpisywaniu metod wirtualnych nie można zmniejszyć
poziomu dostępności (zwiększyć poziomu ochrony):
class Figura {
public String opis(){return ”Jestem Figurą”;}
}
class Kolo extends Figura {
protected String opis(){return ”Jestem Kołem”;}
}
●
// BŁĄD kompilacji
poziom ochrony (dostępności) należy co najmniej zachować
class Kolo extends Figura {
public String opis(){return ”Jestem Kołem”;}
}
Wydział Informatyki Politechniki Białostockiej, Cezary Bołdak
// BŁĄD kompilacji

Podobne dokumenty