"Hei, Amigo! Temaet for dagens leksjon er utvidelse og innsnevring av typekonverteringer. Du har lært om utvidelse og innsnevring av primitive typer for lenge siden. På nivå 10. I dag skal vi snakke om hvordan det fungerer for referansetyper, dvs. forekomster av klasser."

Faktisk er det hele ganske enkelt. Se for deg en klasses arvekjede: klassen, dens overordnede, forelderen til forelderen osv., helt tilbake til Object-klassen. Fordi en klasse inneholder alle medlemsmetoder i klassen den arver , kan en forekomst av klassen lagres i en variabel hvis type er den til en hvilken som helst av dens foreldre.

Her er et eksempel:

Kode Beskrivelse
class Animal
{
public void doAnimalActions();
}class Cat extends Animal
{
public void doCatActions();
}class Tiger extends Cat
{
public void doTigerActions();
}
Her har vi tre klasseerklæringer: Dyr, Katt og Tiger. Katt arver dyr. Og Tiger arver Cat.
public static void main(String[] args)
{
Tiger tiger = new Tiger();
Cat cat = new Tiger();
Animal animal = new Tiger();
Object obj = new Tiger();
}
Et Tiger-objekt kan alltid tilordnes til en variabel hvis type er den til en av dens forfedre. For Tiger-klassen er disse Cat, Animal og Object.

La oss nå ta en titt på utvidelse og innsnevring av konverteringer.

Hvis en tildelingsoperasjon får oss til å bevege oss oppover i arvekjeden (mot Object-klassen), så har vi å gjøre med en utvidende konvertering (også kjent som upcasting). Hvis vi beveger oss nedover kjeden mot objektets type, er det en innsnevrende konvertering (også kjent som nedkasting).

Å bevege seg oppover i arvekjeden kalles utvidelse, fordi det fører til en mer generell type. Ved å gjøre det mister vi imidlertid muligheten til å påkalle metodene som er lagt til klassen gjennom arv.

Kode Beskrivelse
public static void main(String[] args)
{
Object obj = new Tiger();
Animal animal = (Animal) obj;
Cat cat = (Cat) obj;
Tiger tiger = (Tiger) animal;
Tiger tiger2 = (Tiger) cat;
}
Ved innsnevring av typen må du bruke en typekonverteringsoperator, det vil si at vi utfører en eksplisitt konvertering.

Dette får Java-maskinen til å sjekke om objektet virkelig arver typen vi ønsker å konvertere det til.

Denne lille innovasjonen ga en mangfoldig reduksjon i antall typestøpefeil, og økte stabiliteten til Java-programmer betydelig.

Kode Beskrivelse
public static void main(String[] args)
{
Object obj = new Tiger();
if (obj instanceof Cat)
{
Cat cat = (Cat) obj;
cat.doCatActions();
}}
Enda bedre, bruk en  forekomst av sjekk
public static void main(String[] args)
{
Animal animal = new Tiger();
doAllAction(animal);

Animal animal2 = new Cat();
doAllAction(animal2);

Animal animal3 = new Animal();
doAllAction(animal3);
}

public static void doAllAction(Animal animal)
{
if (animal instanceof Tiger)
{
Tiger tiger = (Tiger) animal;
tiger.doTigerActions();
}

if (animal instanceof Cat)
{
Cat cat = (Cat) animal;
cat.doCatActions();
}

animal.doAnimalActions();
}
Og her er hvorfor. Ta en titt på eksempelet til venstre.

Vi (koden vår) vet ikke alltid hvilken type objekt vi jobber med. Det kan være et objekt av samme type som variabelen (Animal), eller en hvilken som helst etterkommertype (Cat, Tiger).

Vurder doAllAction-metoden. Det fungerer riktig, uavhengig av typen objekt som sendes inn.

Med andre ord fungerer det riktig for alle tre typene: Dyr, Katt og Tiger.

public static void main(String[] args)
{
Cat cat = new Tiger();
Animal animal = cat;
Object obj = cat;
}
Her har vi tre oppdragsoperasjoner. Alle er eksempler på utvidede konverteringer.

Typestøpeoperatøren er ikke nødvendig her, fordi ingen sjekk er nødvendig. En objektreferanse kan alltid lagres i en variabel hvis type er en av dens forfedre.

"Å, det nest siste eksemplet gjorde alt klart: hvorfor sjekken er nødvendig, og hvorfor typestøping er nødvendig."

"Jeg håper det. Jeg vil gjøre deg oppmerksom på dette faktum:"

Ingenting av dette får et objekt til å endre seg på noen måte! Det eneste som endres er antall tilgjengelige metoder for å bli kalt på en bestemt referansevariabel.

For eksempel lar en Cat-variabel deg kalle doAnimalActions- og doCatActions-metodene. Den vet ikke noe om doTigerActions-metoden, selv om den peker på et Tiger-objekt.

"Ja, jeg skjønner det. Det var lettere enn jeg trodde det skulle være."