"Hei, Amigo! Her er et emne jeg tror du kommer til å bruke mye av. Jeg snakker om arv. "

For de uinnvidde er programmering som magi. Så la meg starte med en analogi...

Anta at du er en tryllekunstner som ønsker å lage en flygende hest. Du kan prøve å trylle frem en Pegasus. Men siden flygende hester ikke er naturlig forekommende, vil du ha det veldig vanskelig. Du vil ha mye arbeid å gjøre. Det ville være mye lettere å starte med en hest og tilkalle noen vinger.

Arv.  Fordeler med arv - 1

I programmering kaller vi denne prosessen «arv» . Anta at du må skrive en veldig kompleks klasse. Du kan bruke lang tid på å skrive kode fra bunnen av, og deretter utføre lange tester for å finne feil. Men hvorfor gjøre det på den vanskelige måten? Det er bedre å se deg rundt og se om klassen du leter etter allerede eksisterer?

La oss si at du finner en klasse som implementerer 80 % av funksjonaliteten du trenger. Du kan bare kopiere koden til klassen din. Men det vil ha flere ulemper:

1) Klassen du finner kan allerede være kompilert til bytekode. Du har kanskje ikke tilgang til kildekoden.

2) Du har kanskje kildekoden til klassen, men jobber også i et firma som kan bli saksøkt for et par milliarder hvis du bruker til og med 6 linjer med andres kode. Og så vil de saksøke deg.

3) Dette fører til unødvendig duplisering av mye kode. Og hvis forfatteren av den andre klassen finner en feil og fikser den, har du fortsatt feilen.

Det er en mer elegant løsning som ikke krever lovlig tillatelse til koden til den opprinnelige klassen. I Java kan du ganske enkelt erklære den andre klassen som forelder til klassen din. Dette tilsvarer å legge til klassens kode til din egen klasse. Alle dataene og metodene til den overordnede klassen vil vises i klassen din. Du kan for eksempel arve fra en «hest», legge til «vinger», og få en «Pegasus».

Arv.  Fordeler med arv - 2

"Veldig interessant. Vennligst fortsett."

"Arv har andre bruksområder også. Anta at du har ti klasser som er veldig like. De har matchende data og metoder. Du kan lage en spesiell basisklasse , flytte dataene (og tilknyttede metoder) til basisklassen og ha de ti klassene arv fra den. Med andre ord, for hver klasse indikerer du at den har en overordnet klasse, også kjent som en basisklasse."

"Akkurat som fordelene med abstraksjon bare virkelig avsløres i forbindelse med innkapsling, forstørres fordelene med arv av polymorfisme. Men jeg skal fortelle deg om det i morgen. La oss i dag se på noen eksempler på arv."

"Anta at vi skriver et sjakkprogram. Vi trenger klasser for sjakkbrikkene. Hvilke klasser vil du foreslå, Amigo?"

"Konge, Dronning, Biskop, Ridder, Rook og Bonde."

"Veldig bra. Du gikk ikke glipp av noe."

"Og hvilke data vil du foreslå å lagre i disse klassene?"

"Hver brikkes brettposisjon (x og y) og verdi. Tross alt er noen brikker mer verdifulle enn andre."

"Og hva er forskjellene mellom disse klassene?"

"De er forskjellige i hvordan de flytter brikkene. I deres oppførsel."

"Ja. Du kan definere dem som klasser som dette:"

class King
{
int x;
int y;
int worth;
void kingMove()
{
//code that defines,
//how the king moves
}
}
class Queen
{
int x;
int y;
int worth;
void queenMove()
{
//code that defines,
//how the queen moves
}
}
class Rook
{
int x;
int y;
int worth;
void rookMove()
{
//code that defines,
//how the rook moves
}
}
class Knight
{
int x;
int y;
int worth;
void knightMove()
{
//code that defines,
//how the knight moves
}
}
class Bishop
{
int x;
int y;
int worth;
void bishopMove()
{
//code that defines,
//how the bishop moves
}
}
class Pawn
{
int x;
int y;
int worth;
void pawnMove()
{
//code that defines,
//how the pawn moves
}
}

"Ja, det er akkurat slik jeg ville skrevet det."

"Men se på hvordan du kan bruke arv til å skrive mindre kode. Vi kan flytte identiske metoder og data inn i en felles klasse. La oss kalle det ChessItem. Det gir ikke mening å lage ChessItem-objekter, siden de ikke samsvarer med noen sjakk. Men klassen ville vært svært nyttig:"

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

"Hvor interessant!"

"Absolutt! Fordelen er spesielt stor i prosjekter som inneholder tusenvis av forskjellige objekter og hundrevis av klasser. I dette tilfellet kan riktig valgte klasser ikke bare forenkle logikken betydelig, men også redusere den nødvendige koden med en faktor på ti."

"Så hva må du gjøre for å arve en klasse?"

"Etter å ha erklært en klasse, bruker vi nøkkelordet ' forlenger ', etterfulgt av navnet på den overordnede klassen. Du kan bare arve fra én klasse. "

Arv.  Fordeler med arv - 3

Bildet viser en «ku» som har arvet fra en «gris». «Grisen» arver fra «kyllingen», og «kyllingen» arver fra «egget». Hver klasse har kun én forelder! Slik arv er ikke alltid logisk. Hvis du bare har en gris, men du virkelig trenger en ku, kan programmerere ofte ikke motstå ønsket om å lage en «ku» av «grisen».

"Men hva om jeg vil arve fra to klasser? Er det noe jeg kan gjøre?!"

"Ikke egentlig. Java-klasser støtter ikke multippel nedarving av implementering: en klasse kan bare ha en enkelt overordnet klasse. Men det er multippel arv av typen, noe som betyr at en klasse kan implementere mer enn ett grensesnitt. Dette reduserer problemet litt. "

"Jeg skjønner. Og hva er et grensesnitt?"

"Jeg skal fortelle deg om grensesnitt i morgen. La oss foreløpig fortsette å fordype oss i arv."