1. Typecasting

Variabler som lagrer referansetyper (klasser) kan også konverteres til ulike typer. Men dette fungerer bare innenfor et enkelt type hierarki. La oss se på et enkelt eksempel. Anta at vi har følgende klassehierarki, der klassene under arver klassene ovenfor.

Typecasting

Typecasting av referansetyper så vel som primitive er også kategorisert som enten utvidelse og innsnevring.

Vi ser at Cat-klassen arver Pet-klassen, og Pet-klassen på sin side arver Animal-klassen.

Hvis vi skriver kode slik:

Animal kitten = new Cat();

Dette er en utvidende type konvertering . Det kalles også en implisitt rollebesetning. Vi har utvidet kattereferansen slik at den nå refererer til et katteobjekt . Med en typekonvertering som dette vil vi ikke kunne bruke kattungereferansen til å kalle metoder som er tilstede i Cat- klassen, men fraværende i Animal- klassen.

En begrensende konvertering (eller eksplisitt rollebesetning) skjer i motsatt retning:

Cat cat = (Cat) kitten;

Vi indikerte eksplisitt at vi ønsker å kaste referansen som er lagret i kattungevariabelen ( hvis type er Animal ) til Cat- typen.



2. Kontrollere typen til et objekt

Men du må være veldig forsiktig her. Hvis du gjør dette:

Animal beast = new Cat();
Wolf grayWolf = (Wolf) beast;

Kompilatoren vil tillate denne koden, men det vil oppstå en feil når programmet kjører! JVM vil gi et unntak:

Exception in thread "main" java.lang.ClassCastException: Cat cannot be cast to a Wolf

Referanser til et Cat- objekt kan bare lagres i variabler hvis type er en stamfar til Cat-klassen: Pet, Animal eller Object.

Hvorfor det?

Det relevante poenget her er at en objektreferanse brukes til å referere til metodene og variablene til det objektet . Og det vil ikke være noen problemer hvis vi bruker en Animal-variabel til å lagre en referanse til et Cat-objekt: Cat-typen har alltid variabler og metoder av Animal-typen - den har arvet dem!

Men hvis JVM tillot oss å lagre en referanse til et Cat-objekt i en Wolf-variabel, kan vi ha en situasjon der vi kan prøve å bruke grayWolf- variabelen til å kalle en metode som ikke eksisterer i Cat-objektet som er lagret i den variabelen . Det er derfor denne ordningen ikke er tillatt.

Java har en spesiell instanceofoperatør som lar deg sjekke om et objekt er av en bestemt type og derfor kan lagres i en variabel av en bestemt type. Det ser ganske enkelt ut:

variable instanceof Type

Eksempel:

Animal beast = new Cat();
if (beast instanceof Wolf)
{
   Wolf grayWolf = (Wolf) beast;
}

Denne koden vil ikke forårsake feil – selv under kjøring.

Her er noen flere eksempler som illustrerer situasjonen:

Konvertering av utvidende type Beskrivelse
Cow cow = new Whale();

Dette er en klassisk utvidelseskonvertering - ingen typekonverteringsoperatør er nødvendig. Nå kan bare metodene som er definert i Cowklassen kalles på objektet Whale.

cowvariabelen vil kompilatoren bare la deg kalle metoder som dens type ( Cowklassen) har.

Konvertering av smalere type
Cow cow = new Whale();
if (cow instanceof Whale)
{
   Whale whale = (Whale) cow;
}
Klassisk innsnevringskonvertering: Du må legge til en typesjekk og en cast-operatør.
Variabelen Cow cowlagrer en referanse til et Whaleobjekt.
Vi bekrefter at dette er tilfellet , og utfører deretter en konvertering av typen (innsnevring). Eller som det også kalles:
en type cast
.

Cow cow = new Cow();
Whale whale = (Whale) cow; // Exception
Du kan begrense en referansetype uten å sjekke typen til objektet.
Hvis cowvariabelen refererer til et objekt som ikke er en Whale, vil en InvalidClassCastExceptionbli generert.


3. Kalle den opprinnelige metoden: supernøkkelordet

Når vi overstyrer en overordnet klasses metode, noen ganger i stedet for å erstatte den med vår egen, ønsker vi bare å supplere den litt.

Det ville vært kult om vi kunne foreldreklassens metode i metoden vår, og deretter kjøre noe av vår egen kode. Eller kanskje først kjøre vår egen kode, og deretter kalle opp foreldreklassens metode.

Og Java lar oss gjøre nettopp det. For å kalle en metode for overordnet klasse, gjør du dette:

super.method(arguments);

Eksempler:

class PeaceTime
{
   public double getPi()
   {
      return 3.14;
   }
}

class WarTime extends PeaceTime
{
   public double getPi()
   {
      return super.getPi()*2;  // 3.14*2
   }
}

I krigstid kan verdien av Pivære større enn 6! Selvfølgelig tuller vi, men dette eksemplet viser hvordan alt dette kan fungere.

Her er et par flere eksempler for å klargjøre ting litt:

Kode Beskrivelse
class Cow
{
   public void printAll()
   {
      printColor();
      printName();
   }

   public void printColor()
   {
      System.out.println("I'm a white whale");
   }

   public void printName()
   {
      System.out.println("I'm a cow");
   }
}

class Whale extends Cow
{
   public void printName()
   {
      System.out.print("This is incorrect: ");
      super.printName();
      System.out.println("I'm a whale");
   }
}
Cowog Whaleklasser
public static void main(String[] args)
{
   Whale whale = new Whale();
   whale.printAll();
}
Skjermutgangen vil være:
I'm a white whale
This is incorrect: I'm a cow
I'm a whale

Dette er vanskelige greier. Ærlig talt, det er en av de vanskeligste tingene i OOP . Når det er sagt, du trenger å vite og forstå det.