Trashëgimia e Klasave ne C++

Redakto

Përmes mekanizmit të trashëgimisë (ang. inheritance), anëtarët e klasës ekzistuese mund të shfrytëzohen gjatë definimit të klasave të reja. Kjo ka një rëndësi të veçantë, sepse mundësohet plotësimi me komponente i një klase ekzistuese, gjë që mund të shfrytëzohet gjatë përmirësimit të programeve që janë në shfrytëzim, ose të përfshira në biblioteka të ndryshme programesh të gatshme. Klasa ekzistuese njihet si klasë bazë (ang. base class), kurse klasa e re i trashëgon karakteristikat e klasës bazë dhe quhet klasë e nxjerrë (ang. derived class). Klasa e re krijohet duke e plotësuar klasën ekzistuese me anëtarë të tjerë, qofshin ato anëtarë të dhënash ose funksione. Gjatë kësaj, klasa bazë nuk pëson asnjë ndryshim. Njëkohësisht, klasa e nxjerrë mund të shfrytëzohet si klasë bazë për nxjerrjen e klasave të tjera. Një mundësi e tillë e krijimit të klasave të reja, si prej klasave bazë ashtu edhe prej klasave të nxjerra, përmes mekanizmit të trashëgimisë, paraqet një organizim hierarkik të klasave, gjë që programimin e orientuar në objekte e bën edhe më të fuqishëm. Dukja e një organizimi hierarkik të klasave Këtu, nënkuptohet se hierarkia mund të vazhdohet më tutje edhe pas klasës së nxjerrë Profesori. Gjatë kësaj, shigjetat janë të drejtuara prej klasave të nxjerra kah klasa bazë dhe përmes tyre tregohet se prej cilës klasë janë nxjerrë klasat e veçanta. Nëse analizohet hierarkia e dhënë, do të shihet se klasat e nxjerra, në fakt, e plotësojnë klasën bazë me të dhëna dhe funksione të tjera. Kështu, p.sh., nëse te klasa Person përfshihen të dhënat bazike, siç janë emri, vendi, datëlindja etj., përmes klasës së nxjerrë Studenti të dhënat bazë plotësohen, p.sh., me të dhënat për fakultetin, drejtimin e zgjedhur etj. Më tutje, të gjitha këtyre të dhënave mund t'u shtohen edhe ato për provimet e studentëve (klasa e nxjerrë Provimet) dhe për pagesat e tyre (klasa e nxjerrë Pagesat). Meqë shembulli i programit ku do të paraqitej hierarkia e dhënë më sipër, ose edhe pjesë të saj, kërkon më shumë hapësirë, në vijim do të jepen disa shembuj më elementarë. Shembull Programi classT1a, në të cilin definohet klasa Alfa si klasë bazë dhe klasa Beta - si klasë e nxjerrë prej saj.

// Programi classT1a

 #include <iostream>

using namespace std;

class Alfa

{

private:

int a;

public:

double b;

void Jeta()

{

a=5;

b=8;

cout << "\nVlerat te klasa Alfa"

<< "\n\n a="

<< a

<< "\n b="

<< b

<< "\n\n";

}

};

class Beta:public Alfa

{

private:

double c;

public:

int d;

void Dita()

{

b=2;

c=4;

d=7;

cout << "Vlerat te klasa Beta"

<< "\n\n b="

<< b

<< "\n c="

<< c

<< "\n d="

<< d

<< "\n";

}

};

int main()

{

Alfa X;

Beta Y;

X.Jeta();

Y.Dita();

X.Jeta();

return 0;

}

Në program, fillimisht është definuar klasa Alfa. Te funksioni Jeta i cili është deklaruar si publik, variablave a dhe b të klasës u janë shoqëruar vlerat përkatëse 5 dhe 8. Njëkohësisht, përmes komandës cout është urdhëruar shtypja e këtyre vlerave. Pastaj është definuar klasa Beta, në të cilën, përveç komponenteve të saj, janë deklaruar si publike edhe komponentet publike të klasës Alfa, gjë që arrihet përmes deklarimit public Alfa, kështu:

class Beta:public Alfa

Klasa Beta llogaritet si klasë e nxjerrë nga klasa Alfa, meqë brenda saj shfrytëzohen edhe komponentet publike të klasës Alfa.

  • Brenda klasës Alfa mund të shfrytëzohen vetëm variablat a dhe b, si
    dhe funksioni Jeta. Por, nuk mund të shfrytëzohen variablat c e d, si
    dhe funksioni Dita, të cilët paraqiten në komponentet e klasës së
    nxjerrë Beta.
  • Meqë komponentet publike të klasës Alfa janë deklaruar njëkohësisht si
    publike edhe te klasa Beta, te kjo klasë mund të shfrytëzohet edhe
    variabla b, si dhe funksioni Jeta.
  • Brenda klasës Beta nuk mund të shfrytëzohet variabla a, e cila është
    anëtar i klasës Alfa, por e deklaruara si private.

Në program, fillimisht janë deklaruar objektet X dhe Y të klasave Alfa dhe Beta. Pastaj, përmes komandave:

X.Jeta();

Y.Dita();

X.Jeta();

dy herë është thirrë funksioni Jeta dhe një herë funksioni Dita, të cilët përfshihen në komponentet e klasave përkatëse. Nga kjo shihet se, si rezultat i thirrjes dy herë të funksionit Jeta, vlerat që përcaktohen brenda klasës Alfa janë shtypur dy herë. Në shembullin e dhënë, deklarimi i objektit X në programin kryesor është i panevojshëm, sepse pjesa publike e klasës Alfa përfshihet në klasën Beta. Kështu, programi kryesor mund të shkruhet edhe si në vijim.

int main()

{

Beta Y;

Y.Jeta();

Y.Dita();

Y.Jeta();

return 0;

}

Definimi i funksioneve jashtë klasave

Redakto

Me qëllim të rritjes së dukshmërisë së klasave, funksionet që shfrytëzohen brenda tyre edhe në këtë rast mund të definohen jashtë strukturave të tyre, duke i shfrytëzuar format e zakonshme. Shembull Versioni classT1b i programit classT1a, në të cilin definimi i funksioneve bëhet jashtë strukturave të klasave.

// Programi classT1b

#include <iostream>

using namespace std;

class Alfa

{

private:

int a;

public:

double b;

void Jeta();

};

class Beta:public Alfa

{

private:

double c;

public:

int d;

void Dita();

};

int main()

{

Beta Y;

Y.Jeta();

Y.Dita();

Y.Jeta();

return 0;

}

void Alfa::Jeta()

{

a=5;

b=8;

cout << "\nVlerat te klasa Alfa"

<< "\n\n a="

<< a

<< "\n b="

<< b

<< "\n\n";

}

void Beta::Dita()

{

b=2;

c=4;

d=7;

cout << "Vlerat te klasa Beta"

<< "\n\n b="

<< b

<< "\n c="

<< c

<< "\n d="

<< d

<< "\n";

}

Shfrytëzimi i anëtarëve të mbrojtur

Redakto

Anëtarët e klasës bazë do të jenë edhe të mbrojtur, duke e shfrytëzuar specifikuesin e qasjes protected. Këta anëtarë mund të shfrytëzohen plotësisht njëlloj si edhe anëtarët të cilët përfshihen nën specifikuesin private. Por, për dallim nga ata nën specifikuesin private, komponentet nën specifikuesin protected mund të shfrytëzohen edhe te klasat e nxjerra (ato nën specifikuesin private nuk mund të shfrytëzohen te klasat e nxjerra). Anëtarëve të klasës bazë me specifikues të qasjes së mbrojtur nuk mund t'u qasemi nga jashtë sikur edhe atyre me specifikues të qasjes private. Por, anëtarët e klasës, të cilët janë deklaruar si të mbrojtur, mund të shfrytëzohen edhe brenda klasave të nxjerra, gjë që nuk është e mundur për anëtarët me specifikues të qasjes private. Shembull Versioni classT1c i programit classT1b, në të cilin variabla b është përfshirë nën specifikuesin e qasjes së mbrojtur.

// Programi classT1c

#include <iostream>

using namespace std;

class Alfa

{

private:

int a;

protected:

double b;

public:

void Jeta();

};

class Beta:public Alfa

{

private:

double c;

public:

int d;

void Dita();

};

int main()

{

Beta Y;

Y.Jeta();

Y.Dita();

Y.Jeta();

return 0;

}

Pjesa tjetër e programit, që nuk është dhënë, në të cilën përcaktohen funksionet Jeta dhe Dita, mbetet e njëjtë me atë që shihet te programi classT1b. Kjo do të thotë se variabla b në komponenten e mbrojtur të klasës Alfa shfrytëzohet edhe te klasa e nxjerrë Beta.

Shfrytëzimi i anëtarëve gjatë trashëgimisë

Redakto

Anëtarët e klasës bazë bëhen edhe anëtarë të klasës së nxjerrë. Te klasa e nxjerrë mund t'u qasemi direkt anëtarëve publikë dhe anëtarëve të mbrojtur të klasës bazë. Por, nuk lejohet qasja direkte tek anëtarët e mbrojtur të klasës bazë, prej klasës së nxjerrë. Qasja direkte te anëtarët privat të klasës bazë është e mundshme vetëm brenda klasës bazë. Anëtarët publikë të klasës bazë trashëgohen te klasa e nxjerrë si anëtarë publikë, kurse anëtarët privatë ose të mbrojtur, varësisht nga specifikuesi i qasjes që zgjedhet gjatë definimit të klasës së nxjerrë, ashtu siç është dhënë në vijim.

1.class Alfa

{

...

};

class Beta:public Alfa

{

...

};

Këtu, anëtarët publikë të klasës Alfa trashëgohen te klasa e nxjerrë Beta si anëtar publik.

2.class Alfa

{

...

};

class Beta:private Alfa

{

...

};

Në këtë rast, anëtarët publikë të klasës Alfa te klasa e nxjerrë Beta trashëgohen si anëtar privat.

3.class Alfa

{

...

};

class Beta:Alfa

{

...

};

Meqë këtu nuk është shënuar specifikuesi i qasjes, kompjuteri e nënkupton atë si private. Prandaj, në këtë rast, si edhe në rastin paraprak, anëtarët publikë të klasës Alfa trashëgohen si anëtarë privatë te klasa e nxjerrë Beta.

4.class Alfa

{

...

};

class Beta:protected Alfa

{

...

};

Në këtë rast, pasi specifikuesi i qasjes për anëtarët e trashëguar është protected, anëtarët publikë të klasës Alfa do të jenë anëtarë të mbrojtur te klasa e nxjerrë Beta. Pas definimit të klasës së nxjerrë, vlejnë rregullat e qasjes për klasat e zakonshme, si tek anëtarët e saj, ashtu edhe tek anëtarët e trashëguar nga klasa bazë. Klasa bazë nuk ka qasje tek anëtarët e klasës së nxjerrë, përkatësisht prej saj nuk mund të shihen komponentet e pjesës tjetër të hierarkisë së klasave në të cilën ajo përfshihet. Çdo klasë e nxjerrë bëhet klasë bazë për klasat të cilat nxirren prej saj.

Trashëgimia e shumëfishtë

Redakto

Gjatë krijimit të klasave përmes trashëgimisë, klasa e re mund të nxirret prej një klase bazë, ose edhe prej më shumë klasave bazë njëkohësisht. Në këto dy raste flitet për trashëgimi të njëfishtë (ang. single inheritance) dhe trashëgimi të shumfishtë (ang. multiple inheritance). Te shembujt që u dhanë në pjesën paraprake kemi të bëjmë me trashëgiminë e njëfishtë, sepse anëtarët e trashëguar të klasës së nxjerrë janë anëtarë të vetëm një klase bazë. Këtu, klasa e nxjerrë X i trashëgon vetëm anëtarët e klasës bazë A, gjë që, siç është dhënë më parë, në program shkruhet si në vijim.

class A

{

...

};

class X:public A

{

...

};

Specifikuesi i qasjes te klasa e nxjerrë X, për anëtarët e trashëguar nga klasa A, siç u pa në shembujt paraprakë, përveç public, mund të jenë edhe private dhe protected. Një shembull i trashëgimisë së shumëfishtë, kur klasa X është nxjerrë nga dy klasat bazë A dhe B. Gjatë definimit të trashëgimisë nga shembulli në fjalë, definimi i relacioneve të klasave do të duket si në vijim.

class A

{

...

};

class B

{

...

};

class X:public A,public B

{

...

};

Nënkuptohet se edhe këtu specifikuesit e qasjes te klasa e nxjerrë X, për anëtarët e trashëguar nga klasat A dhe B, si te rastet e trashëgimisë së njëfishtë, përveç public, mund të jenë edhe private dhe protected. Trashëgimia e shumëfishtë mund të jetë edhe komplekse, kur si klasa bazë paraqiten edhe klasa të nxjerra.

Në program, definimi i relacioneve të klasave në këtë rast do të mund të shkruhej ashtu siç është dhënë në vijim.

class A

{

...

};

class B:public A

{

...

};

class C:public A

{

...

};

class X:public B,public C

{

...

};

Referim

Redakto

Agni Dika, "Programimi i Orientuar në Objekte në C++" 2007.