"Amigo, liker du hval?"
"Hval? Nei, aldri hørt om dem."
"Den er som en ku, bare større og den svømmer. Hvaler kom forresten fra kuer. Uh, eller i det minste deler de en felles stamfar. Det spiller ingen rolle."

"Hør her. Jeg vil fortelle deg om et annet veldig kraftig verktøy for OOP: polymorfisme . Det har fire funksjoner."
1) Metodeoverstyring.
Tenk deg at du har skrevet en "Ku"-klasse for et spill. Den har mange medlemsvariabler og metoder. Objekter i denne klassen kan gjøre forskjellige ting: gå, spise, sove. Kyr ringer også i bjelle når de går. La oss si at du har implementert alt i klassen ned til minste detalj.

Så plutselig sier kunden at han vil slippe et nytt nivå av spillet, der alle handlinger foregår i havet, og hovedpersonen er en hval.
Du begynte å designe Whale-klassen og innse at den bare er litt annerledes enn Cow-klassen. Begge klassene bruker veldig lik logikk, og du bestemmer deg for å bruke arv.
Cow-klassen er ideell til å være foreldreklassen: den har allerede alle nødvendige variabler og metoder. Alt du trenger å gjøre er å legge til hvalens evne til å svømme. Men det er et problem: hvalen din har bein, horn og en bjelle. Tross alt implementerer Cow-klassen denne funksjonaliteten. Hva kan du gjøre?

Metodeoverstyring kommer til unnsetning. Hvis vi arver en metode som ikke gjør akkurat det vi trenger i vår nye klasse, kan vi erstatte metoden med en annen.

Hvordan gjøres dette? I vår etterkommerklasse erklærer vi metoden vi ønsker å endre (med samme metodesignatur som i overordnet klasse) . Deretter skriver vi ny kode for metoden. Det er det. Det er som om foreldreklassens gamle metode ikke eksisterer.
Slik fungerer det:
Kode | Beskrivelse |
---|---|
|
Her definerer vi to klasser: Cow og Whale . Whale arver Cow .
Klassen |
|
Denne koden viser « Jeg er en ku » på skjermen. |
|
Denne koden viser « Jeg er en hval » på skjermen |
Etter at den har arvet Cow
og overstyrt printName
, Whale
har klassen faktisk følgende data og metoder:
Kode | Beskrivelse |
---|---|
|
Vi vet ingenting om noen gammel metode. |
"Ærlig talt, det var det jeg forventet."
2) Men det er ikke alt.
"Anta at Cow
klassen har en printAll
metode som kaller de to andre metodene. Da vil koden fungere slik:"
Skjermen vil vise:
Jeg er hvit,
jeg er en hval
Kode | Beskrivelse |
---|---|
|
|
|
Skjermen vil vise: Jeg er hvit, jeg er en hval |
Merk at når Cow-klassens printAll ()-metode kalles på et Whale-objekt, vil Whale's printName()-metoden bli brukt, ikke Cow's.
Det viktige er ikke klassen metoden er skrevet i, men snarere type (klasse) av objektet som metoden kalles på.
"Jeg skjønner."
"Du kan bare arve og overstyre ikke-statiske metoder. Statiske metoder er ikke arvet og kan derfor ikke overstyres."
Slik ser Whale-klassen ut etter at vi har brukt arv og overstyrt metodene:
Kode | Beskrivelse |
---|---|
|
Slik ser hvalklassen ut etter at vi har brukt arv og overstyrt metoden. Vi vet ingenting om noen gammel printName metode. |
3) Type støping.
Her er et enda mer interessant poeng. Fordi en klasse arver alle metodene og dataene til den overordnede klassen, kan et objekt i denne klassen refereres til av variabler fra den overordnede klassen (og overordnet til overordnet, etc., helt opp til objektklassen). Tenk på dette eksemplet:
Kode | Beskrivelse |
---|---|
|
Skjermen vil vise: Jeg er hvit. |
|
Skjermen vil vise: Jeg er hvit. |
|
Skjermen vil vise: Whale@da435a. Metoden toString() er arvet fra Object-klassen. |
"Bra greier. Men hvorfor skulle du trenge dette?"
"Det er en verdifull funksjon. Du vil forstå senere at den er veldig, veldig verdifull."
4) Sen binding (dynamisk utsendelse).
Slik ser det ut:
Kode | Beskrivelse |
---|---|
|
Skjermen vil vise: Jeg er en hval. |
|
Skjermen vil vise: Jeg er en hval. |
Merk at det ikke er typen av variabelen som bestemmer hvilken spesifikk printName- metode vi kaller (den for Cow- eller Whale-klassen), men snarere typen objekt som variabelen refererer til.
Cow - variabelen lagrer en referanse til et Whale- objekt, og printName- metoden definert i Whale- klassen vil bli kalt.
"Vel, det la de ikke til for ordens skyld."
"Ja, det er ikke så åpenbart. Husk denne viktige regelen:"
Settet med metoder du kan kalle på en variabel bestemmes av variabelens type. Men hvilken spesifikk metode/implementering som blir kalt, bestemmes av typen/klassen til objektet som variabelen refererer til.
"Jeg skal prøve."
"Du vil støte på dette hele tiden, så du vil raskt forstå det og aldri glemme."
5) Type støping.
Støping fungerer annerledes for referansetyper, altså klasser, enn det gjør for primitive typer. Utvidende og innsnevrede konverteringer gjelder imidlertid også for referansetyper. Tenk på dette eksemplet:
Utvidende konvertering | Beskrivelse |
---|---|
|
En klassisk utvidelseskonvertering. Nå kan du bare kalle metoder definert i Cow-klassen på Whale-objektet. Kompilatoren lar deg bare bruke cow-variabelen for å kalle de metodene som er definert av Cow-typen. |
Begrensende konvertering | Beskrivelse |
---|---|
|
En klassisk innsnevringskonvertering med typesjekk. Cow - variabelen av typen Cow lagrer en referanse til et hvalobjekt. Vi sjekker at dette er tilfellet , og utfører deretter (utvidende) typekonvertering. Dette kalles også typestøping . |
|
Du kan også utføre en innsnevringskonvertering av en referansetype uten å typesjekke objektet. I dette tilfellet, hvis cow- variabelen peker på noe annet enn et Whale-objekt, vil et unntak (InvalidClassCastException) bli kastet. |
6) Og nå til noe velsmakende. Kaller den opprinnelige metoden.
Noen ganger når du overstyrer en nedarvet metode, vil du ikke helt erstatte den. Noen ganger vil du bare legge til litt.
I dette tilfellet vil du virkelig at den nye metodens kode skal kalle den samme metoden, men på basisklassen. Og Java lar deg gjøre dette. Slik gjøres det: super.method()
.
Her er noen eksempler:
Kode | Beskrivelse |
---|---|
|
|
|
Skjermen vil vise: Jeg er hvit Dette er falskt: Jeg er en ku jeg er en hval |
"Hmm. Vel, det var en leksjon. Robotørene mine smeltet nesten."
"Ja, dette er ikke enkle ting. Det er noe av det vanskeligste materialet du vil møte. Professoren lovet å gi lenker til materiale fra andre forfattere, slik at hvis du fortsatt ikke forstår noe, kan du fylle ut hull."
GO TO FULL VERSION