Klasy abstrakcyjne, interfejsy i polimorfizm

Transkrypt

Klasy abstrakcyjne, interfejsy i polimorfizm
Klasy abstrakcyjne, interfejsy i polimorfizm
Programowanie obiektowe
Janusz Jabłonowski
12 kwietnia 2011
Janusz Jabłonowski
Klasy abstrakcyjne, interfejsy i polimorfizm
Organizacyjne
Klasówka bedzie
˛
20 IV 2011.
Sale jeszcze sa˛ pertraktowane.
Materiał do wyjatków
˛
włacznie.
˛
Można mieć swoje materiały nieelektroniczne.
Janusz Jabłonowski
Klasy abstrakcyjne, interfejsy i polimorfizm
Wywołanie z super może nie być intuicyjne
1
2
3
4
public class A {
public void m1 ( ) { System . o u t . p r i n t l n ( "A" ) ; }
}
5
6
7
8
9
10
11
12
public class B extends A{
public void m2 ( ) {
System . o u t . p r i n t ( " super .m1 ( ) −> " ) ;
super .m1 ( ) ;
System . o u t . p r i n t ( " t h i s .m1 ( ) −> " ) ;
t h i s .m1 ( ) ;
}
13
@Override
public void m1 ( ) { System . o u t . p r i n t l n ( "B" ) ; }
14
15
16
}
Janusz Jabłonowski
Klasy abstrakcyjne, interfejsy i polimorfizm
Wywołanie z super może nie być intuicyjne
1
2
3
4
5
6
7
8
public class C extends B{
public void m3 ( ) {
m2 ( ) ; / / Czy wypisze A czy B?
}
@Override
public void m1 ( ) { System . o u t . p r i n t l n ( "C" ) ; }
}
Janusz Jabłonowski
Klasy abstrakcyjne, interfejsy i polimorfizm
Wywołanie z super może nie być intuicyjne
1
2
3
4
5
B b = new B ( ) ;
b .m2 ( ) ;
C c = new C ( ) ;
c .m2 ( ) ;
c .m3 ( ) ;
I wynik:
super.m1() -> A
this.m1() -> B
super.m1() -> A
this.m1() -> C
super.m1() -> A
this.m1() -> C
Janusz Jabłonowski
Klasy abstrakcyjne, interfejsy i polimorfizm
Klasy abstrakcyjne
Nie maja˛ obiektów (bezpośrednio swojej klasy).
Kompilator odrzuci próbe˛ utworzenia obiektu takiej klasy.
Sa˛ bardzo ważne!
Pozwalaja˛ wyabstrahować wspólne cechy wielu pojeć
˛ (klas).
Zapewniaja˛ wspólny interfejs dla swoich podklas.
Zapewniaja˛ jednocześnie wspólna˛ implementacje.
˛
Typowe zastosowaie - wiele implementacji tego samego pojecia.
˛
Klasy abstrakcyjne - klasy konkretne.
Janusz Jabłonowski
Klasy abstrakcyjne, interfejsy i polimorfizm
Składnia klas abstrakcyjnych
Klasa abstrakcyjna jest deklarowana ze słowem abstract.
Klasa abstrakcyjna nie musi mieć metod abstrakcyjnych, choć
zwykle ma.
Metoda abstrakcyjna jest deklarowana ze słowem abstract i nie
może mieć treści.
Musi być podmieniona na konkretna˛ w konkretnych podklasach.
Klasa, która nie podmieni choć jednej odziedziczonej metody
abstrakcyjnej lub ma własna˛ metode abstrakcyjna˛ musi być
zadeklarowana jako abstrakcyjna.
Można wywoływać metody abstrakcyjne (dlaczego nie ma w tym
nic gorszacego?).
˛
Można też podmienić metode˛ konkretna˛ na abstrakcyjna!
˛
Janusz Jabłonowski
Klasy abstrakcyjne, interfejsy i polimorfizm
Przykład klasy abstrakcyjnej
1
2
3
a b s t r a c t class Pojemnik {
public a b s t r a c t void dodaj ( i n t e l t ) ;
/ / Powyższe jest ciekawe - wymusza implementacje˛ w podklasach
4
public void dodajTab ( i n t [ ] t a b ) {
for ( i n t i : tab )
dodaj ( i ) ;
}
/ / Powyższe jest ciekawe - konkretna metoda w abstrakcyjnej klasie
/ / wywołuje abstrakcyjna˛ metode˛
5
6
7
8
9
10
11
@Override
public a b s t r a c t S t r i n g t o S t r i n g ( ) ;
/ / Powyższe jest ciekawe - toString było zdefiniowane w Object
12
13
14
15
}
16
17
/ / Całe powyższe jest zatem ciekawe QED.
Janusz Jabłonowski
Klasy abstrakcyjne, interfejsy i polimorfizm
Przykład podklasy klasy abstrakcyjnej
1
2
public class PojemnikTablicowy extends Pojemnik {
/ / Niezm.: dane sa˛ w tab[0..ile-1]
3
4
5
6
PojemnikTablicowy ( ) {
t a b = new i n t [ 1 ] ; / / 1024 byłoby bardziej naturalne
}
7
8
9
private i n t [ ] tab ;
p r i v a t e i n t i l e =0;
Janusz Jabłonowski
Klasy abstrakcyjne, interfejsy i polimorfizm
Przykład podklasy klasy abstrakcyjnej cd
1
2
3
4
5
6
7
8
9
10
11
12
@Override
public void dodaj ( i n t e l t ) {
i f ( i l e >= t a b . l e n g t h ) {
i n t [ ] pom = new i n t [ t a b . l e n g t h ∗ 2 ] ;
f o r ( i n t i =0; i < i l e ; i ++)
pom [ i ] = t a b [ i ] ;
/ / System.arraycopy(tab, 0, pom, 0, ile);
t a b = pom ;
/ / nie ma to jak automatyczne odśmiecanie :)
}
/ / teraz już na pewno jest miejsce
t a b [ i l e ++] = e l t ;
}
Janusz Jabłonowski
Klasy abstrakcyjne, interfejsy i polimorfizm
Przykład podklasy klasy abstrakcyjnej cd
1
2
3
4
5
6
7
8
9
10
11
@Override
public S t r i n g t o S t r i n g ( ) {
S t r i n g wyn= " [ " ; / / Powinien być StringBuilder
f o r ( i n t i =0; i < i l e −1; i ++)
wyn += t a b [ i ] + " , " ;
i f ( i l e >0)
wyn+= t a b [ i l e − 1 ] ;
wyn+= " ] " ;
r e t u r n wyn ;
} / / toString
} / / PojemnikTablicowy
Janusz Jabłonowski
Klasy abstrakcyjne, interfejsy i polimorfizm
Przykład użycia tej hierarchii klas
1
2
3
4
5
6
7
8
9
10
public s t a t i c void t e s t ( ) {
i n t [ ] dane = { 1 , 3 , 8 , 2 , 5 , 9 , 8 } ;
Pojemnik p = new PojemnikTablicowy ( ) ;
System . o u t . p r i n t l n ( " p = " + p ) ;
f o r ( i n t e l t : dane )
p . dodaj ( e l t ) ;
System . o u t . p r i n t l n ( " p = " + p ) ;
p . dodajTab ( dane ) ;
System . o u t . p r i n t l n ( " p = " + p ) ;
}
I wynik:
p = []
p = [1, 3, 8, 2, 5, 9, 8]
p = [1, 3, 8, 2, 5, 9, 8, 1, 3, 8, 2, 5, 9, 8]
Janusz Jabłonowski
Klasy abstrakcyjne, interfejsy i polimorfizm
Przykład dziwnej hierarchii klas
1
2
3
public a b s t r a c t class A bs t ra k cy j na A {
public a b s t r a c t void m( ) ;
}
4
5
6
7
8
9
public a b s t r a c t class A bs t ra k cy j na B extends A bs t ra kc y jn a A {
@Override
public a b s t r a c t void m( ) ;
/ / można podmienić abstrakcyjna˛ metode˛ na abstrakcyjna,
˛ tylko po co?
}
10
11
12
13
14
15
16
public class KonkretnaC extends A bs t ra k cy jn a B {
@Override
public void m( ) {
System . o u t . p r i n t l n ( " AbstrakcyjnaC .m( ) " ) ;
}
}
Janusz Jabłonowski
Klasy abstrakcyjne, interfejsy i polimorfizm
Przykład dziwnej hierarchii klas
1
2
3
public a b s t r a c t class AbstrakcyjnaD extends KonkretnaC {
/ / klasa abstrakcyjna może dziedziczyć po konkretnej
}
4
5
6
public class KonkretnaE extends AbstrakcyjnaD {
}
7
8
9
A bs t ra k c y j n a A a = new KonkretnaE ( ) ;
a .m( ) ;
I wynik:
AbstrakcyjnaC.m()
Janusz Jabłonowski
Klasy abstrakcyjne, interfejsy i polimorfizm
Interfejsy
Klasy abstrakcyjne bez żadnej implementacji.
Jeszcze lepsza postać kontraktu.
Nie da sie˛ utworzyć obiektu z interfejsu (ale można obiekt klasy
impelmentujacej
˛
interfejs).
Można (i bardzo czesto
˛
tak sie˛ robi) zadeklarować zmienna˛ o
typie bed
˛ acym
˛
interfejsem.
Interfejs może dziedziczyć po interfejsie (używa sie˛ wtedy słowa
extends).
Interfejs nie może dziedziczyć po klasie.
Tak klasa jak i interfejs moga˛ dziedziczyć po dowolnie wielu
interfejsach.
Interfejsy daja˛ wiec
˛ namiastke˛ wielodziedziczenia.
Janusz Jabłonowski
Klasy abstrakcyjne, interfejsy i polimorfizm
Składnia interfejsów
Domyślnie wszystkie składowe sa˛ rozumiane jako publiczne (i
słowa public nie pisze sie.
˛
Stałe interfejsu to atrybuty z public, static final . Te modyfikatory
sa˛ przyjmowane domyślnie.
Nie maja˛ składowych klasowych (tj. ze słowem static ) poza
stałymi.
Nie maja˛ składowych bed
˛ acych
˛
atrybutami (poza stałymi).
Klasa dziedziczaca
˛ po interfejsie albo implementuje wszystkie
jego metody (i wtedy może być konkretna lub może być
abstrakcyjna), albo nie wszystkie (w szczególności żadnej) i
wtedy musi być abstrakcyjna.
Janusz Jabłonowski
Klasy abstrakcyjne, interfejsy i polimorfizm
Składnia interfejsów
Każdy interfejs niedziedziczacy
˛ po innym niejawnie ma
dodawane nagłówki publicznych metod klasy Object — wszystko
(prawie) w Javie jest obiektem.
Interfejs może zawierać tylko:
stałe (pola),
metody,
zagnieżdżone klasy i interfejsy.
Janusz Jabłonowski
Klasy abstrakcyjne, interfejsy i polimorfizm
Składnia interfejsów - interfejs Pojemnik
1
2
3
4
5
public i n t e r f a c e Pojemnik {
void wstaw ( i n t i ) ;
int pobierz ( ) ;
boolean p u s t y ( ) ;
}
Janusz Jabłonowski
Klasy abstrakcyjne, interfejsy i polimorfizm