04-Nasljedjivanje

Download Report

Transcript 04-Nasljedjivanje

Nasljeđivanje





Pojam nasljeđivanja
Definisanje izvedenih klasa
Prava pristupa u izvedenim klasama
Pozivanje konstruktora i destruktora
Klasni dijagrami





Jedan on najvažnijih OOP koncepata
Omogućava ponovno korištenje koda tako što se
koriste postojeće klase za izvođenje novih
Često se sreće slučaj da je jedna klasa objekata
(klasa B) podvrsta neke druge klase (klasa A)
◦ Geometrijske figure u ravni su klasa koja je
okarakterisana koordinatama težišta. Krug je
vrsta figure u ravni koja je okarakterisana
dužinom poluprečnika. Kvadrat je vrsta figure u
ravni koja je okarakterisana dužinom ivice.
Objekti klase B imaju sve osobine klase A i još neke
specijalne, sebi svojstvene osobine
Specijalnija klasa B se izvodi iz generalnije klase A

Opisuje relaciju “je tipa” ili “je vrste”
◦ Predstavlja odnos između klasa
◦ Nove klase specijaliziraju postojeće klase
Generalizacija
Musician
Osnovna klasa
Specijalizacija
Violin
Player
Primjer nasljeđivanja
Izvedena klasa



Klasa B nasljeđuje osobine klase A
Ovakva relacija između klasa naziva se
nasljeđivanje (engl. inheritance)
Relacija nasljeđivanja se najčešće
prikazuje usmjerenim grafom
A
B
specijalizacija
generalizacija
Figura
2Dfigura
Krug
Kvadrat
3DFigura
Trougao
Sfera
Kupa
Tetraedar

Klase povezane relacijama nasljeđivanja
formiraju hijerarhije klasa
Musician
String
Musician
???
Violin
Player
plays
Musical
Instrument
plays
Stringed
Instrument
plays
Violin
???


Izvođenje iz jedne osnovne klase
Izvođenje iz više osnovnih klasa
Stringed
Instrument
Violin
Musical
Instrument
Pluckable
Stringed
Instrument


Naziv metode definisan u osnovnoj klasi
Implementacija metode definisana u
izvedenim klasama
String Musician
TuneYourInstrument( )
Guitar Player
Violin Player
TuneYourInstrument( )
TuneYourInstrument( )

Neke klase se definišu samo da se na osnovu
njih kreiraju izvedene klase
◦ Nema smisla kreirati instance ovih klasa
◦ Ove klase se nazivaju apstraktne
Stringed Musician
{ abstract }
Guitar Player
« concrete »
Violin Player
« concrete »

Interfejsi sadrže samo operacije (nazive
funkcija bez njihove implementacije)
Musician
« interface »
Ne mogu se kreirati
instance interfejsa
String Musician
{ abstract }
Mogu sadržati implementaciju
Ne mogu se kreirati instance
apstraktnih klasa
Violin Player
« concrete »
Moraju implementirati sve
naslijeđene operacije.
Mogu se kreirati instance klase

Ako je klasa B naslijedila klasu A (izvedena iz
klase A), kaže se još da je:
◦ klasa A osnovna klasa (engl. base class), a klasa B
izvedena klasa (engl. derived class);
◦ klasa A nadklasa (engl. superclass), a klasa B
podklasa (engl. subclass);
◦ klasa A roditelj (engl. parent), a klasa B dijete (engl.
child).

Izvedena klasa se definiše navođenjem
sljedeće konstrukcije između identifikatora
klase i znaka {
public
:
osnovna
klasa-e
virtual
protected
private
,
class Osnovna {
int i;
public:
void f();
};
// privatni podatak clan osnovne klase
// javna funkcija clanica osnovne klase
class Izvedena : public Osnovna {
int j;
// privatni podatak clan izvedene klase
public:
void g();
};
// javna funkcija clanica izvedene klase
void main () {
Osnovna b; Izvedena d;
b.f();
b.g();
// GRESKA: g je funkcija izvedene klase, a b je objekat osnovne
d.f();
// objekat izvedene klase d ima i funkciju f,
d.g();
// i funkciju g
}

Sintaksa za definisanje nasljeđivanja
class Token
Izvedena
Osnovna
{
...
}
class CommentToken: Token
{
...
}


Token
« concrete »
CommentToken
« concrete »
Izvedena klasa nasljeđuje većinu elemenata svoje
osnovne klase
Pristup naslijeđenim članovima izvedene klase ne
može biti višeg nivoa nego u osnovnoj klasi





Redefinisanje identifikatora iz osnovne klase unutar izvedene
klase sakriva identifikator iz osnovne klase.
Pristup sakrivenom članu iz osnovne klase unutar izvedene
klase je moguć na način: <osnovna klasa>::<član> (C++).
Izvedena klasa nema pravo pristupa privatnim članovima
osnovne klase.
Labela protected: označava dio klase koji je pristupačan kako
članicama tako i funkcijama izvedenih klasa.
Članovi u ovoj sekciji se nazivaju zaštićenim članovima (engl.
protected members).
class Osnovna {
int p;
protected:
int z;
public:
int j;
};
class Izvedena : public Osnovna {
public:
void write(int x) {
j=z=x; // moze da pristupi javnom i zasticenom clanu,
p=x;
// ! GRESKA: privatnom clanu se ne moze
pristupiti
}
};
void f() {
Osnovna b;
b.z=5;
zasticenom clanu
}
// odavde ne moze da se pristupa
class Token
{
...
protected string name;
}
class CommentToken: Token
{
...
public string Name( )
{
return name;
}
}



class Outside
{
void Fails(Token t)
{
...
t.name
...
}
}

Naslijeđeni zaštićeni (protected) članovi su implicitno
zaštićeni i u izvedenoj klasi
Metode izvedene klase mogu pristupiti samo naslijeđenim
članovima (protected, public) ili vlastitim novim članovima
definisanim u izvedenoj klasi



Privatno (podrazumijevano ako se ne navede drugo) –
svi naslijeđeni članovi postaju privatni u izvedenoj
klasi
Zaštićeno – svi naslijeđeni članovi postaju zaštićeni u
izvedenoj klasi
Javno – prava pristupa se ne mijenjaju u odnosu na
osnovnu klasu (javni ostaju javni, zaštićeni ostaju
zaštićeni)
Pristup u osnovnoj
klasi
Nepristupačan
Privatni
Zaštićeni
Javni
Pristupačnost u
privatno izvedenoj
klasi
Nepristupačan
Nepristupačan
Privatni
Privatni
Pristupačnost u
zaštićeno izvedenoj
klasi
Nepristupačan
Nepristupačan
Zaštićeni
Zaštićeni
Pristupačnost u javno
izvedenoj klasi
Nepristupačan
Nepristupačan
Zaštićeni
Javni

Nasljeđivanje implementacije (implementation
inheritance)
◦ Izvedena klasa nasljeđuje osobine druge klase,
atribute i metode, uključujući implementaciju
metoda

Nasljeđivanje interfejsa (interface inheritance)
◦ Izvedena klasa nasljeđuje samo potpise metoda iz
jednog ili više interfejsa, bez implementacije
metoda



Pri kreiranju objekta izvedene klase poziva
se konstruktor te klase, ali i konstruktor
osnovne klase.
U zaglavlju definicije konstruktora izvedene
klase, u listi inicijalizatora, moguće je
navesti i inicijalizator osnovne klase
(argumente poziva konstruktora osnovne
klase).
To se radi navođenjem imena osnovne klase
i argumenata poziva konstruktora osnovne
klase

class Osnovna {
int bi;
public:
Osnovna(int); // konstruktor osnovne klase
};
Osnovna::Osnovna (int i) : bi(i) {/*...*/}

class Izvedena : public Osnovna {
int di;
public:
Izvedena(int);
};

Izvedena::Izvedena (int i) : Osnovna(i),di(i+1)
{/*...*/}

Rezervisana riječ base
class Token
{
protected Token(string name) { ... }
...
}
class CommentToken: Token
{
 A private base class constructor cannot be accessed by a
publicclass
CommentToken(string name) : base(name) { }
derived
...the base keyword to qualify identifier scope
 Use
}

Pri kreiranju objekta izvedene klase
redoslijed poziva konstruktora je sljedeći:
◦ inicijalizuje se podobjekat osnovne klase,
pozivom konstruktora osnovne klase;
◦ inicijalizuju se podaci članovi, eventualno
pozivom njihovih konstruktora, po redoslijedu
deklarisanja;
◦ izvršava se tijelo konstruktora izvedene klase.

Pri uništavanju objekta, redoslijed poziva
destruktora je uvek obratan.
class Element {
public:
Klasa() {cout<<"Konstruktor klase Element .\n";}
~Klasa() {cout<<"Destruktor klase Element .\n";}
};
class Osnovna {
public:
Osnovna() {cout<<"Konstruktor osnovne klase."<<endl;}
~Osnovna() {cout<<"Destruktor osnovne klase."<<endl;}
};
class Izvedena : public Osnovna {
Element x;
public:
Izvedena() {cout<<"Konstruktor izvedene klase."<<endl;}
~Izvedena() {cout<<"Destruktor izvedene klase."<<endl;}
};
void main () {
Izvedena d;
}
/* Izlaz programa:
Konstruktor osnovne klase.
Konstruktor klase Element.
Konstruktor izvedene klase.
Destruktor izvedene klase.
Destruktor klase Element.
Destruktor osnovne klase.
*/



Višestruko nasljeđivanje (engl. multiple
inheritance) omogućava nasljeđivanje
osobina više osnovnih klasa
Klasa se deklariše kao nasljednik više klasa
tako što se u zaglavlju deklaracije navode
osnovne klase.
Ispred svake osnovne klase treba da stoji
riječ public, da bi izvedena klasa
nasljeđivala prava pristupa članovima.
class Izvedena : public Osnovna1, public
Osnovna2, private Osnovna3 {/* ... */};




Sva pravila o nasljeđenim članovima važe i
kod višestrukog nasljeđivanja.
Konstruktori osnovnih klasa se pozivaju
prije konstruktora članova izvedene klase i
konstruktora izvedene klase.
Konstruktori osnovnih klasa se pozivaju po
redoslijedu deklarisanja.
Destruktori osnovnih klasa se izvršavaju na
kraju, poslije destruktora izvedene klase i
destruktora članova.
x
x
Osnovna
Izv1
?X
?X
x
VIzv
Izv2
class Osnovna {
public: int x;
};
class Izv1 : public Osnovna {/*...*/};
class Izv2 : public Osnovna {/*...*/};
class VIzv : public Izv1, public Izv2 {
public: int fun();
};




Ako klasa ima višestruku nevirtuelnu osnovnu klasu X onda
će objekti te klase imati više podobjekata tipa X
Članovima osnovne klase X može se pristupiti
nedvosmislenim navođenjem njihove pripadnosti,
korišćenjem operatora : :
VIzv :: Izv1 :: Osnovna :: X
Konverzija pokazivača tj reference na izvedenu klasu u
pokazivač/referencu na višestruku osnovnu klasu može se
izvršiti samo ako je nedvosmislena
Nedvosmislenost znači da ne postoje dva ili više entiteta koja
odgovaraju navedenom imenu
void VIzv :: fun()
{
x=2;
// dvosmislenost, Izv1::X ili Izv2::X , greška !!!
Izv1::x = Izv2::x + 1; // ispravno
}
x
x
Osnovna
Izv1
?X
?X
x
VIzv
x Osnovna
Izv2
x
x
Izv1
x
Osnovna
Izv2
x
VIzv
x
Nije dozvoljeno da jedna klasa bude višestruka direktna osnovna klasa!
class A : public X, public X { };




Osnovna klasa može biti virtuelna – treba je
deklarisati kao virtuelnu sa virtual
Ako je osnovna klasa virtuelna onda se podobjekti
osnovne klase unutar objekta izvedene klase dijele
sa svim podobjektima koji imaju istu osnovnu
klasu kao virtuelnu
Obraćanje članu osnovne klase nije dvosmisleno
ako postoji samo jedan primerak tog člana bez
obzira na način pristupa
Ako je potrebno da izvedena klasa posjeduje samo
jedan podobjekat indirektne osnovne klase onda
osnovnu klasu treba deklarisati kao virtuelnu
class
class
class
class
B {/*...*/};
X : virtual public B {/*...*/};
Y : virtual public B {/*...*/};
Z : public X, public Y {/*...*/};
B
X
Y
Z
Klasa Z ima samo jedan skup članova klase B.
Moraju se i X i Y virtuelno izvesti iz B;
Ako je samo jedna izvedena virtuelno ostaju dva skupa članova.
Konstruktori virtuelnih osnovnih klasa se pozivaju prije
konstruktora nevirtuelnih osnovnih klasa.
Svi konstruktori osnovnih klasa se pozivaju prije konstruktora
članova i konstruktora izvedene klase.

Nije podržano nasljeđivanje iz više direktnih
osnovnih klasa
◦ Ne postoji mogućnost višestrukog nasljeđivanja za
slušaj nasljeđivanja implementacije

Moguće je nasljeđivanje iz više interfejsa
◦ Višestruko nasljeđivanje može se primijeniti samo
za slučaj nasljeđivanja interfejsa

Rezervisana riječ interface
Imena interfejsa obično
počinju slovom “I”
interface IToken
{
int LineNumber( );
string Name( );
}
Bez modifikatora pristupa
IToken
« interface »
LineNumber( )
Name( )
Bez implementacije

Klasa može implementirati više interfejsa (ili nijedan)
interface IToken
IToken
IVisitable
{
« interface »
« interface »
string Name( );
}
interface IVisitable
{
void Accept(IVisitor v);
}
Token
class Token: IToken, IVisitable
« concrete »
{ ...
}



Interfejs može naslijediti više drugih interfejsa (ili nijedan)
Prava pristupa u klasi mogu biti višeg nivoa nego u
interfejsima
Klasa mora implementirati sve naslijeđene metode interfejsa


Metoda koja implementira metodu interfejsa
mora biti ista kao metoda interfejsa
Implementirajuća metoda može biti virtuelna
ili nevirtuelna
class Token: IToken, IVisitable
{
public virtual string Name( )
{ ...
}
public void Accept(IVisitor v)
{ ...
}
}
Isti povratni tip
Isto ime
Isti parametri