Pređi na sadržaj

Nasleđivanje (objektno-orijentisano programiranje)

S Vikipedije, slobodne enciklopedije

Nasleđivanje je kada objekat ili klasa bazira na drugom objektu (prototipsko programiranje) ili klasi (klasno-orijentisano programiranje), koristeći istu implementaciju (nasleđenu od objekta ili klase), specifirajući implementaciju da se ponaša isto (interfejsing; nasleđeno ponašanje). To je mehanizam za ponovno korišćenje koda koji omogućava nezavisnost ekstenzije od originalnog softvera pomoću klasa i interfejsa. Odnos objekata ili klasa tokom nasleđivanja je doprineo razvoju hijerarhije. Nasleđivanje je osmišljeno 1967, u Simuli.[1]

Nasleđivanje ne bi trebalo da bude konfuzno sa podtipom.[2][3] U nekim jezicima se nasleđivanje i podtipovi slažu,[a]dok su u nekim programskim jezicima različiti; generalno podtip uspostavlja je-a relaciju, dok nasleđivanje samo ponovo koristi implementaciju i ustostavlja sintatičku ravnotežu, ne stalno i semantičku (Nasleđivanje ne garantuje podtipsko ponašanje). Da bismo razlikovali ove koncepte, kažemo i da je sabtajping poznat i kao interfejsno nasleđivanje, dok je nasleđivanje opisano kao nasleđivanje implementacija ili nasleđivanje koda.[4]  Nasleđivanje je najčešće korišćen mehanizam za uspostavljanje ravnoteže podtipskih relacija.[5]

Nasleđivanje čini objektna kompozicija, gde jedan objekat sadrži drugi objekat (ili objekat jedne klase sadrži objekat druge klase), vidi kompoziciju preko nasleđivanja. Kompozicije implementiraju ima-a ravnotežu, što je suprotno od ravnoteže koju uspostavlja podtip (je-a).

Tipovi nasleđivanja[uredi | uredi izvor]

Jednostruko nasleđivanje
Višesložno i višestruko nasleđivanje

Postoje različiti tipovi nasleđivanja,[6] baziranih na paradigmalnom i specifičnom programiranju.

Jednostruko nasleđivanje
Kada podklasa nasleđuje osobine jedne super klase. Klasa dobija osobine druge klase.
Višestruko nasleđivanje
Kada jedna klasa može da ima više roditeljskih klasa i nasleđuje osobine svih roditeljskih klasa.
Višesložno nasleđivanje
: kada je podklasa nsleđena od druge podklase. Nije neuobičajeno da je klasa izvedena od druge izvedene klase kao što i sam naslov govori "Višesložno nasleđivanje". Klasa A je baza za izvedenu klasu B, dok je klasa B baza za izvedenu klasu C. Za klasu B se kaže da je srednja baza-klasa jer predstavlja vezu za nasleđivanje između klase A i klase C. Lanac ABC se još naziva i putanja nasleđivanja.

Izvedena klasa višesložnog nasleđivanja:

Class A(...); //Родитељска класа
Class B : public A(...); //B изведена из A
Class C : public B(...); //C изведена B

Ovaj proces se može proširiti na višebrojni nivo.

Hijerarhijsko nasleđivanje
kada je jedna klasa-superklasa (bazna klasa) za više podklasa.
Hibridno nasleđivanje
od dva ili više tipa nasleđivanja.

Podklase i superklase[uredi | uredi izvor]

 Podklasa, izvedena klasa, dečija klasa, je modularna , derivatna klasa koja nasleđuje jedno ili više jezičkih entiteta od jedne ili više drugih klasa (superklasa, bazna klasa, roditeljska klasa). Semantika nasleđivanja klase varira od programa do programa, ali uglavnom podklase automatski nasleđuju varijable i članove funkcija iz superklase. Opšti oblik definisanja izvedene klase je:  

class derived-class-name : visibility-mode base-class-name
{
 .....//
 .....// чланови изведене класе
 .....//
};
  • Dvotačka označava da je izvedena klasa ime, izvedena iz bazne klase ime. Vidljivost je opcionalna i može biti skrivena ili javna. Proizvoljno izabrani mod je skriven. Vidljivost karakteriše baznu klasu skriveno ili javno.

Neki programi podržavaju nasleđivanje i drugih konstrukcija. Npr. u Ajfelu, „ugovor“ koji karakteriše specifikaciju klasa, karakteriše i naslednike. Superklasa omogućava zajednički pristup i osnivačku funkcionalnost, što dovodi do toga da podklase mogu da nasleđuju, modifikuju i suplementiraju. Softversko nasleđivanje uz pomoć podklasa je ponovo korišćeno u podklasama. Referenca instance klase može se odnositi na neku od njenih podklasa. Stvarnu klasu ovjekata koja je referencovana, teško je predvideti u prevedeno vreme. Jedinstveni pristup se koristi da se pozovu članovi funkcije broja objekata druih klasa. Podklasa može da zameni funkcije superklase sa potpuno novim funkcijama koje moraju da imaju istu metodu.

Nenasledne klase[uredi | uredi izvor]

U nekim programima klasa može biti označena kao nenasledna, dodajući klasne modifikatore u opis klase. Primeri uključuju finalnu ključnu reč u Javi ili zaglavljenu ključnu reč u C#. Takvi modifikatori su dodati u klasnoj deklaraciji pre klasne ključne reči i klasnog pronalazača deklaracije. Tako zaglavljene klase imaju ograničenu upotrebljivost, kada jedino developeri imaju pristup reorganizovanom binarnom fajlu ili izvornom kodu.

Zaglavljena klasa nema podlkase, tako da može biti odbijena u složenom vremenu, tako da su reference ili pokazivački objekta klase referencne instance klasa ali ne i instance podklasa (koje ne postoje) ili instance superklasa. Podtipski polimorfizam. Zato što je tačan tip objekta bio referencovan pre izvršenja,rano vezivanje (statično obaveštenje) može biti korišćeo umesto kasnog vezivanja (još poznato i kao „dinamično obaveštenje), koja podrazumeva jednu ili više virtualnih metoda tabela, čiji izgled zavisi od toga da li program podržava višesložno nasleđivanje ili jednosložno nasleđivanje

Metode koje ne mogu biti preskočene[uredi | uredi izvor]

Klase mogu biti zatvorene/završene, deklaracija metoda može da sadrži modifikator metoda koji sprečava da se metod preskoči (i.e. zameniti novom funkcijom sa istim imenom i tipom u podklasi). Skriven metod je veoma jednostavan zato što nije dostupan drugim klasa osim klasi koja je član funkcije (ovo nije tačno u C++). Finalna metoda u Javi, skrtivena metoda u C# ili zaleđena osobina u Ajfelu ne mogu biti preskočene.

Virtualne metode[uredi | uredi izvor]

Ako je metoda superklase virtualna metoda, prizivanje superklasnih metoda će biti dinamično poslato. Neki programi podrazumevaju da metode budu specifično deklarisano kao virtualne (npr. C++) u nekim programima sve metode su virtualne (npr. Java). Pozivi ne-virtualne metode će biti uvek statički poslate (adresa poziva funkcije se nalazi u složenom-vremenu). Statično slanje je brže od dinamičkog i sadrži optimizam koji se naziva staza za proširenje.

Vidljivost nasleđenih članova[uredi | uredi izvor]

Base class 

vidljivost

Vidljivost izvedene klase
Javna

derivacija

Privatna

derivacija

Osigurana

derivacija

  • Skrivena →
  • Osigurana →
  • Javna →
  • Nenasleđena
  • Osigurana
  • Javna
  • Nenasleđena
  • privatna
  • privatna
  • Nenasleđena
  • Osigurana
  • Osigurana

[7]

Aplikacije[uredi | uredi izvor]

Aplikacije se koriste da dve ili više klase umreže.

  • Prelazak preko 

Mnogi objektno-orijentisani programski jezici dopuštaju klasi ili objektu da zamene implementaciju jednog aspekta-u glavnom ponašanje-koje je nasledio. Ovaj proces se često zove prelazak preko. Prelazak preko zahteva kompilaciju: koja verzija ponašanja ima instancu nasleđene klase-deo te date klase ili deo iz roditeljske (bazne) klase? Odgovor varira u zavisnosti od programskog jezika, dok su neki jezici razvili sposobnost da pokažu da partikularno ponašanje neće biti pređeno i da treba da se ponaša kao što je definisano od strane roditeljske klase. Na primer, u C#, bazne metode mogu biti pređene samo u podklasi ako su označene virutalnom, apstraktnom ili pređi preko modifikatorom.[8] Alternativa za prelazak preko jeskrivanje nasleđenog koda.

  • Ponovna upotreba koda

Nasleđivanje implementacije je mehanizam kojim podklasa ponovo koristi kod u roditeljskoj klasi. Podklasa sadrži sve operacije roditeljske klase, ali podklasa može preći preko nekih ili svih operacija , zamenjujući implementaciju roditeljske klase, svojom implementacijom.

U pratećem Pajtonovom primeru, podklasa  CubeSumComputer pregazila je transform() metodu roditeljske klase  SquareSumComputer. Roditeljska klasa sadrži operacije za izračunavanje sume korena između dva broja. Podklasa koristi sve funkcije roditeljske klase sa izuzetkom operacije koja transformiše broj u kvadat tog broja, ta funkcija je zamenjena operacijom koja transformiše broj u kub. Podklasa izralunava sumu kubova između dva broja.

class SquareSumComputer(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b

    def transform(self, x):
        return x * x

    def inputs(self):
        return range(self.a, self.b)

    def compute(self):
        return sum(self.transform(value) for value in self.inputs())

class CubeSumComputer(SquareSumComputer):
    def transform(self, x):
        return x * x * x

U većini kvartala, klasno nasleđivanje ima jedinu namenu u vidu reupotrebe. Primarna briga je ta što nasleđena implementacija ne obezbeđuje uverenje u polimorfnu zamensku moć- instanca ponovne upotrebe klase ne može neminovno biti zamenjena za instancu nasleđene klase. Alternativni način, delegacija, zahteva veći napor od strane programa, ali izbegava pitanje zamene. U C++ skriveno nasleđivanje može biti korišćeno u formi nasleđene implementacije bez zamene. Dok javno nasleđivanje predstavlja je-a vezu i delegacija predstavlja ima-a vezu, skriveno (i osigurano) nasleđivanje se može posmatrati kao veza jeste implementirano u zavisnosti od [9]

Još jedno često korišćenje nasleđivanja jeste da bi se garantovalo da klase održavaju određeni zajednički pristup; tj. da implementiraju iste metode. Roditeljska klasa može biti kombinacija implementiranih operacija i operacija koje su implementirane u dečijim klasama. Često, ne postoji pristup promene između dva podtipa i pod tipa - ponašanje dečije implementacije je opisano njenom roditeljskom klasom.[10]

Nasleđivanje protiv podtipova[uredi | uredi izvor]

Nasleđivanje je slično ali i različito od podtipskog polimorfizma.[11]  Podtip omogućava da dati tip bude zamenjen za drugi tip ili apstrakciju, i rečeno je već da uspostavlja "je-a" relaciju između podtipa i neke postojeće apstrakcije, implicitno ili eksplicitno, u zavisnosti od programa. Relacija se može predstaviti eksplicitno uz pomoć nasleđivanja u programima koji podržavaju nasleđivanje kao mehanizam podtipa. Na primer, kod u C++ uspostavlja eksplicitnu relaciju nasleđivanja između klasa B i A, gde je B i podklasa i podtip od A, i može biti korišćen kao A kad god je B određeno ( uz pomoć referenci, indikatora ili sopstvenog objekta)

class A 
{ public:
   void DoSomethingALike() const {}
};

class B : public A 
{ public:
   void DoSomethingBLike() const {}
};

void UseAnA(A const& some_A)
{
   some_A.DoSomethingALike();
}

void SomeFunc()
{
   B b;
   UseAnA(b); // b може бити замењено са A.
}

U programima koji ne podržavaju nasleđivanje kao poditpski mehanizam, relacija između bazne klase i izvedene klase je jedino relacija između implementacija (mehanizam za ponovnu upotrebu koda), uporedno relaciji između tipova. Nasleđivanje, čak i u programskim jezicima koji podržavaju nasleđivanje kao mehanizam podtipova, ne mora nužno zahtevati podtipsko ponašanje. U potpunosti je moguće izvesti klasu čiji će se objekat ponašati loše kada je korišćen u kontekstu gde je očekivana roditeljska klasa; videti Liskov princip zamene.[12]

Dizajnirana ograničenja[uredi | uredi izvor]

Korišćenje nasleđivanja ekstenzivno u dizajniranju programa nameće neka ograničenja.

Na primer, razmotrimo klasu Person koja sadrži ime osobe, datum rođenja, adresu i broj telefona. Možemo definisati podklasu klase Person i nazvati je Student koja sadrži prosek ocena iz klase Person, i drugu podklasu klase Person koju nazivamo Employee koja sadrži naslov posla, zaposlene i platu iz klase Person.

U definisanju ove hijerarhije nasleđivanja, već smo definisali neka ograničenja, ali ne sva ograničenja koja su neophodna:

Usamljenost
Koristeći jedno nasleđivanje, podklasa može naslediti od samo jedne superklase. Nastavljajući gorenavedeni primer, Person klasa može biti ili Student ili Employee, ali ne oba. Koristeći multiplativno nasleđivanje pri parcijalnom rešavanju ovog problema,  kao jedan se može definisati StudentEmployee klasa koja nasleđuje iz obe klase Stuent i Employee. U većini implementacija, se samo jednom može naslediti iz svake superklase, i to tako, da ne podržava slučajeve kada student ima dva posla ili pohađa dve institucije. Model nasleđivanja dostupan u Ajfelu čini ovo mogućim kroz podršku za ponavljačko nasleđivanje.
Statičnost
Hijerarhija nasleđivanja nekog objetka je fiksirana u instanci kada je tip objekta označen i ne menja se tokom vremena. Na primer, grafikonsko nasleđivanje ne dozvoljava Student objektu da postane Employe objekat dok je  zadržana roditeljska klasa Person. (Ovakav tip ponašanja, može biti dostignuto uz pomoć dekoratora izuma. Nekolicina je kritikovala nasleđivanje, tvrdeći da ograniči developere u njihove originalne dizajnerske standarde  .[15]
Vidljivost
Kad god kod klijenta ima pristup nekom objektu, on ustvaru ima pristup svim objektima superklase. Čak i ako superklasa nije deklarisana javno, klijent i dalje može odrediti objekat superklase. Na primer, ne postoji mnogo načina dati funkciju  izvršioca  studentovoj(klasa Student) srednjoj oceni i  prepis bez davanja pristupa toj funkciji za sve personalne tipove sačuvane u studentovoj Person superklasi. Mnogo modernih jezika, uključujući C++ i Javu, ima „zaštitni „pristup modifikatora koji omogućuje podklasama prisutup podacima, bez uvođenja bilo kakvog koda izvan lanca nasleđivanja za pristup.

Kompozitna ponovna upotreba principa je zamena za nasleđivanje. Ova tehnika podržava polimorfizam i ponovno korišćenje koda različitih ponašanja od primarne klase u hijerarhiji i uključujući specifično ponašanje klasa potrebnih u bilo kakvoj biznis-domenskoj klasi. Ovaj pristup izbegava statičnu prirodu hijerarhije klase dozvoljavajući promenu ponašanja u brzom vremenu i dozvoljava jednoj klasi da implemetira ponašanje („bufet stil“), umesto da bude ograničena na ponašanje roditeljskih klasa.

Pitanja i alternative[uredi | uredi izvor]

Nasleđivanje implementacije je kontroverza između programera i teoretičara objektnog-orijentisanog programiranja nastala u 1990-im. Između njih su autori dizajnerskih izuma, koji su podržali pristup nasleđivanja,  i usluge kompozicije preko nasleđivanja. Na primer dekoratorni izum (kao što je spomenuto) je predložen da se prevaziđe statička priroda nasleđivanja između klasa. Kao više fundamentalno rešenje za isti problem, programiranje orijentisano na ulogama uvodi posebnu relaciju, odigranu od strane, kombinujući svojstva nasleđivanja i kompozicije u novi koncept.

Prema rečima Alena Holuba, glavni problem sa nasleđivanjem implementacije je to što podrazumeva nepotrebno zaustavljanje (kvačilo) u formi „Krhka bazna klasa- problem:[4]modifikacija implementacije bazne klase može slučajno izazvati promenu u superklasama.[15] Drugačije rečeno, ovo je „Nasleđivanje zaustavlja enkapsulaciju „.[13] Problem jasno izbija na površinu u otvorenim objektno-orijentisanim sistemima kao što su okviri, gde je očekivano da klijentni kod nasledi od sistema-isporučene klase i nakon toga zameni sistemske klase u svojim algoritmima  .[4]

Navodno, inovator Jave Džejms Gozling je bio protiv nasleđivanja implementacije, govoreći da on neće učestvovati u redizajniranju Jave.[14] Programski dizajn koji razdvaja nasleđivanje od podtipova (nasleđivanje pristupa) se pojavilo još u ranim 90-im;[15] modrni primer ovoga je programski jezik Gou.

Kompleksno nasleđivanje, ili nasleđivanje korišćeno sa nedovoljno složenim dizajnom, može dovesti do jo-jo problema.

Drugi problem sa nasleđivanjem je to što podklasa mora biti definisana u kodu, što znači da korisnici programa ne mogu dodavati nove podklase.

Vidi još[uredi | uredi izvor]

Napomene[uredi | uredi izvor]

  1. ^ Ovo je generalno istina samo u statično-pisanim, klasno-orijentisanim objektno orijentisanim programima kao što su C++, C#, Java, i Skala.

Reference[uredi | uredi izvor]

  1. ^ Mintz & Ekendahl 2006, str. 22.
  2. ^ Cook, William R.; Hill, Walter; Canning, Peter S. (1990).
  3. ^ Cardelli, Luca (1993).
  4. ^ Mikhajlov, Leonid; Sekerinski, Emil (1998).
  5. ^ Tempero, Ewan; Yang, Hong Yul; Noble, James (2013).
  6. ^ "Inheritance in C++".
  7. ^ Balagurusamy, E. (2010). Object Oriented Programming With C++. Tata McGraw Hill. str. 213. ISBN 978-0-07-066907-9. 
  8. ^ override(C# Reference)
  9. ^ "GotW #60: Exception-Safe Class Design, Part 2: Inheritance".
  10. ^ Venugopal, K.R.; Buyya, Rajkumar (2013). Mastering C++. Tata McGraw Hill Education Private Limited. str. 609. ISBN 9781259029943. 
  11. ^ Cook, Hill & Canning 1990.
  12. ^ Mitchell, John (14. 10. 2002). „Concepts in object-oriented languages”. Concepts in Programming Languages. str. 287. ISBN 9781139433488. 
  13. ^ Seiter, Linda M.; Palsberg, Jens; Lieberherr, Karl J. (1996).
  14. ^ Holub, Allen (1 August 2003).
  15. ^ America, Pierre (1991).

Literatura[uredi | uredi izvor]