1. Pegas

Să aruncăm o privire mai profundă asupra celui de-al treilea principiu al POO : moștenirea . Acesta este un subiect foarte interesant pe care îl veți folosi des. Pentru cei neinițiați, programarea nu se poate distinge de magie. Deci să începem cu o analogie interesantă...;

Să presupunem că ești un vrăjitor care vrea să creeze un cal zburător. Pe de o parte, ai putea încerca să evocați un pegas. Dar pentru că pegasii nu există în natură, acest lucru va fi foarte dificil. Va trebui să faci multe singuri. Este mult mai ușor să iei un cal și să-i evoci aripile.

În programare, acest proces se numește „moștenire”. Să presupunem că trebuie să scrieți o clasă foarte complexă. Este nevoie de mult timp pentru a scrie codul de la zero și apoi testați totul pentru o lungă perioadă de timp pentru a căuta erori. De ce să mergi pe calea grea? Este mai bine să te uiți pentru a vedea dacă o astfel de clasă există deja.

Să presupunem că găsiți o clasă ale cărei metode implementează 80% din funcționalitatea de care aveți nevoie. Ce faci cu el mai departe? Puteți doar să copiați codul său în clasa dvs. Dar această soluție are mai multe dezavantaje:

  1. Clasa pe care o găsiți poate fi deja compilată în bytecode și este posibil să nu aveți acces la codul sursă.
  2. Codul sursă al clasei este disponibil, dar lucrezi pentru o companie care ar putea fi dat în judecată pentru câteva miliarde pentru că folosește chiar și 6 linii din codul altcuiva. Și atunci angajatorul tău te va da în judecată.
  3. Dublarea inutilă a unei cantități mari de cod. În plus, dacă autorul unei clase externe găsește o eroare în ea și o remediază, veți avea în continuare eroarea.

Există o soluție mai elegantă și nu necesită acces legal la codul clasei originale. În Java, puteți declara pur și simplu acea clasă ca părinte a clasei dvs. Acest lucru va fi echivalent cu adăugarea codului pentru acea clasă la propriul cod. Clasa ta va vedea toate datele și toate metodele clasei părinte. De exemplu, puteți face acest lucru: moștenim „cal” și apoi adăugăm „aripi” pentru a obține un „pegas”


2. Clasa de bază comună

Moștenirea poate fi folosită și în alte scopuri. Să presupunem că aveți zece clase care sunt foarte asemănătoare. Au aceleași date și metode. Puteți crea o clasă de bază specială, puteți muta datele (și metodele asociate) în această clasă de bază și puteți declara că acele zece clase sunt descendente. Cu alte cuvinte, în fiecare clasă indicați că clasa sa părinte este această clasă de bază.

Așa cum avantajele abstracției sunt dezvăluite numai de-a lungul încapsulării laterale, la fel și avantajele moștenirii sunt mult îmbunătățite atunci când se utilizează polimorfismul. Dar veți afla despre asta puțin mai târziu. Astăzi vom analiza câteva exemple de utilizare a moștenirii.

Piese de șah

Să presupunem că scriem un program care joacă șah cu un utilizator uman. În consecință, avem nevoie de clase pentru a reprezenta piesele. Ce clase ar fi?

Dacă ați jucat vreodată șah, răspunsul evident este Regele, Regina, Episcopul, Cavalerul, Turnul și Pionul.

Dar clasele în sine ar trebui să stocheze informații despre fiecare piesă. De exemplu, coordonatele x și y și valoarea piesei. La urma urmei, unele piese sunt mai valoroase decât altele.

În plus, piesele se mișcă diferit, ceea ce înseamnă că clasele vor implementa un comportament diferit. Iată cum le puteți defini ca clase:

class King
{
   int x;
   int y;
   int worth;

   void kingMove()
   {
     // Code that decides
     // how to move
     // the king
   }
}
class Queen
{
   int x;
   int y;
   int worth;

   void queenMove()
   {
     // Code that decides
     // how to move
     // the queen
   }
}
class Rook
{
   int x;
   int y;
   int worth;

   void rookMove()
   {
     // Code that decides
     // how to move
     // the rook
   }
}
class Knight
{
   int x;
   int y;
   int worth;

   void knightMove()
   {
     // Code that decides
     // how to move
     // the knight
   }
}
class Bishop
{
   int x;
   int y;
   int worth;

   void bishopMove()
   {
     // Code that decides
     // how to move
     // the bishop
   }
}
class Pawn
{
   int x;
   int y;
   int worth;

   void pawnMove()
   {
     // Code that decides
     // how to move
     // the pawn
   }
}

Aceasta este o descriere foarte primitivă a pieselor de șah.

Clasa de bază comună

Și iată cum ați putea folosi moștenirea pentru a reduce cantitatea de cod. Putem aduce metodele și datele comune într-o clasă comună. Îl vom numi ChessItem. Nu are rost să creezi obiecte din ChessItem class, deoarece clasa nu corespunde nici unei piese de șah . Acestea fiind spuse, clasa se va dovedi foarte utilă:

class King extends ChessItem
{
   void kingMove()
   {
     // Code that decides
     // how to move the king
   }
}
class Queen extends ChessItem
{
   void queenMove()
   {
     // Code that decides
     // how to move the queen
   }
}
class Rook extends ChessItem
{
   void rookMove()
   {
     // Code that decides
     // how to move the rook
   }
}
class ChessItem
{
   int x;
   int y;
   int worth;
}
class Knight extends ChessItem
{
   void knightMove()
   {
     // Code that decides
     // how to move the knight
   }
}
class Bishop extends ChessItem
{
   void bishopMove()
   {
     // Code that decides
     // how to move the bishop
   }
}
class Pawn extends ChessItem
{
   void pawnMove()
   {
     // Code that decides
     // how to move the pawn
   }
}

Aceasta este o modalitate excelentă de a simplifica codul pentru obiecte similare. Beneficiile sunt deosebit de vizibile atunci când există mii de obiecte diferite și sute de clase în proiect. Prin urmare, clasele părinte (de bază) selectate corespunzător vă permit nu numai să simplificați foarte mult logica, dar și să reduceți codul de zece ori.


3. Moștenirea de clasă —extends

Deci, ce este nevoie pentru a moșteni o clasă? Pentru ca o clasă să moștenească alta, trebuie să scrieți cuvântul extendscheie după declarația clasei copil și apoi să scrieți numele clasei părinte. De obicei arată cam așa:

class Descendant extends Parent

Acesta este ceea ce trebuie să scrieți atunci când declarați clasa Descendent. Apropo, o clasă poate moșteni o singură clasă.

În imagine, vedem că o vaca a moștenit un porc, care a moștenit un pui, care a moștenit un ou. Un singur părinte! O astfel de moștenire nu este întotdeauna logică. Dar atunci când tot ce ai este un porc și chiar ai nevoie de o vacă, programatorii nu pot rezista adesea nevoii de a face o vaca dintr-un porc.

Java nu are moștenire multiplă: o clasă nu poate moșteni două clase. Fiecare clasă poate avea o singură clasă părinte. Dacă nu este specificată nicio clasă părinte, clasa părinte este Object.

Acestea fiind spuse, Java are o moștenire multiplă de interfețe. Acest lucru atenuează ușor problema. Vom vorbi despre interfețe puțin mai târziu, dar deocamdată să continuăm să explorăm moștenirea.