1. Pegasus

La oss ta en dypere titt på det tredje prinsippet for OOP : arv . Dette er et veldig interessant emne som du vil bruke ofte. For de uinnvidde er programmering umulig å skille fra magi. Så la oss starte med en interessant analogi...;

La oss si at du er en trollmann som ønsker å lage en flygende hest. På den ene siden kan du prøve å trylle frem en pegasus. Men fordi pegasi ikke finnes i naturen, vil dette være veldig vanskelig. Du må gjøre mye selv. Det er mye lettere å ta en hest og trylle med vingene.

I programmering kalles denne prosessen "arv". Anta at du må skrive en veldig kompleks klasse. Det tar lang tid å skrive kode fra bunnen av og deretter teste alt i lang tid for å se etter feil. Hvorfor gå den harde veien? Det er bedre å se om en slik klasse allerede eksisterer.

Anta at du finner en klasse hvis metoder implementerer 80 % av funksjonaliteten du trenger. Hva gjør du med det neste? Du kan bare kopiere koden til klassen din. Men denne løsningen har flere ulemper:

  1. Klassen du finner kan allerede være kompilert til bytekode, og du har kanskje ikke tilgang til kildekoden.
  2. Kildekoden til klassen er tilgjengelig, men du jobber for et selskap som kan bli saksøkt for et par milliarder for å bruke til og med 6 linjer med andres kode. Og så vil arbeidsgiveren saksøke deg.
  3. Unødvendig duplisering av en stor mengde kode. I tillegg, hvis forfatteren av en ekstern klasse finner en feil i den og fikser den, vil du fortsatt ha feilen.

Det er en mer elegant løsning, og den krever ikke å få lovlig tilgang til den originale klassens kode. I Java kan du ganske enkelt erklære den klassen som forelder til klassen din. Det vil tilsvare å legge til koden for den klassen til din egen kode. Klassen din vil se alle dataene og alle metodene til den overordnede klassen. For eksempel kan du gjøre dette: vi arver "hest" og legger deretter til "vinger" for å få en "pegasus"


2. Felles grunnklasse

Arv kan også brukes til andre formål. La oss si at du har ti klasser som er veldig like. De har samme data og metoder. Du kan opprette en spesiell basisklasse, flytte dataene (og tilknyttede metoder) inn i denne basisklassen, og erklære de ti klassene som etterkommere. Med andre ord, i hver klasse indikerer at dens overordnede klasse er denne basisklassen.

Akkurat som fordelene med abstraksjon bare avsløres langs sideinnkapsling, er fordelene med arv også mye forbedret når man bruker polymorfisme. Men du vil lære om det litt senere. I dag skal vi se på flere eksempler på bruk av arv.

Sjakkbrikker

Anta at vi skriver et program som spiller sjakk med en menneskelig bruker. Følgelig trenger vi klasser for å representere brikkene. Hvilke klasser ville de vært?

Hvis du noen gang har spilt sjakk, er det åpenbare svaret Konge, Dronning, Biskop, Ridder, Rook og Bonde.

Men klassene selv må fortsatt lagre informasjon om hver del. For eksempel x- og y-koordinatene, og verdien av brikken. Tross alt er noen stykker mer verdifulle enn andre.

I tillegg beveger brikkene seg forskjellig, noe som betyr at klassene vil implementere ulik oppførsel. Slik kan du definere dem som klasser:

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
   }
}

Dette er en veldig primitiv beskrivelse av sjakkbrikker.

Felles grunnklasse

Og her er hvordan du kan bruke arv for å redusere mengden kode. Vi kan bringe de vanlige metodene og dataene inn i en felles klasse. Vi kaller det ChessItem. Det er ingen vits i å lage objekter av ChessItem class, siden klassen ikke samsvarer med noen sjakkbrikke . Når det er sagt, vil klassen vise seg å være veldig nyttig:

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
   }
}

Dette er en fin måte å forenkle koden for lignende objekter. Fordelene er spesielt merkbare når det er tusenvis av forskjellige objekter og hundrevis av klasser i prosjektet. Så riktig valgte overordnede (base) klasser lar deg ikke bare i stor grad forenkle logikken, men også redusere koden tidoblet.


3. Klassearv –extends

Så hva skal til for å arve en klasse? For at en klasse skal arve en annen, må du skrive nøkkelordet extendsetter barneklasseerklæringen og deretter skrive navnet på den overordnede klassen. Det ser vanligvis omtrent slik ut:

class Descendant extends Parent

Dette er hva du må skrive når du erklærer Descendant-klassen. En klasse kan forresten bare arve én klasse.

På bildet ser vi at en ku arvet en gris, som arvet en kylling, som arvet et egg. Kun én forelder! Slik arv er ikke alltid logisk. Men når alt du har er en gris og du virkelig trenger en ku, kan programmerere ofte ikke motstå trangen til å lage en ku av en gris.

Java har ikke multippel arv: en klasse kan ikke arve to klasser. Hver klasse kan bare ha én overordnet klasse. Hvis ingen overordnet klasse er spesifisert, er overordnet klasse Object.

Når det er sagt, har Java flere grensesnittarv. Dette reduserer problemet litt. Vi skal snakke om grensesnitt litt senere, men la oss foreløpig fortsette å utforske arv.