1. Typecasting

Variabler, der gemmer referencetyper (klasser), kan også konverteres til forskellige typer. Men dette virker kun inden for et enkelt type hierarki. Lad os se på et simpelt eksempel. Antag, at vi har følgende klassehierarki, hvor klasserne nedenfor arver klasserne ovenfor.

Typecasting

Typecasting af referencetyper såvel som primitive er også kategoriseret som enten udvidelse og indsnævring.

Vi ser, at Cat-klassen arver Pet-klassen, og Pet-klassen til gengæld arver Animal-klassen.

Hvis vi skriver kode sådan her:

Animal kitten = new Cat();

Dette er en udvidende type konvertering . Det kaldes også en implicit cast. Vi har udvidet kattereferencen , så den nu refererer til et Cat- objekt. Med en typekonvertering som denne vil vi ikke kunne bruge killinge- referencen til at kalde metoder, der er til stede i Cat -klassen, men fraværende i Animal- klassen.

En indsnævrende konvertering (eller eksplicit rollebesætning) sker i den modsatte retning:

Cat cat = (Cat) kitten;

Vi har eksplicit angivet, at vi ønsker at støbe referencen, der er gemt i killingens variabel (hvis type er Animal ) til Cat- typen.



2. Kontrol af typen af ​​et objekt

Men du skal være meget forsigtig her. Hvis du gør dette:

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

Compileren vil tillade denne kode, men der vil være en fejl, når programmet kører! JVM vil kaste en undtagelse:

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

Referencer til et Cat- objekt kan kun gemmes i variabler, hvis type er en forfader af Cat-klassen: Pet, Animal eller Object.

Hvorfor det?

Det relevante her er, at en objektreference bruges til at henvise til det pågældende objekts metoder og variabler . Og der vil ikke være nogen problemer, hvis vi bruger en Animal-variabel til at gemme en reference til et Cat-objekt: Cat-typen har altid variabler og metoder af Animal-typen - den har arvet dem!

Men hvis JVM'en tillod os at gemme en reference til et Cat-objekt i en Wolf-variabel, så kunne vi have en situation, hvor vi kunne prøve at bruge grayWolf- variablen til at kalde en metode, der ikke findes i Cat-objektet, der er gemt i den variabel . Derfor er denne ordning ikke tilladt.

Java har en speciel instanceofoperator, der lader dig kontrollere, om et objekt er af en bestemt type og derfor kan lagres i en variabel af en bestemt type. Det ser ret simpelt ud:

variable instanceof Type

Eksempel:

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

Denne kode vil ikke forårsage fejl - heller ikke under kørsel.

Her er nogle flere eksempler, der illustrerer situationen:

Udvidelsestypekonvertering Beskrivelse
Cow cow = new Whale();

Dette er en klassisk udvidelseskonvertering - ingen typekonverteringsoperatør er påkrævet. Nu kan kun de metoder, der er defineret i Cowklassen, kaldes på Whaleobjektet.

cowvariablen vil compileren kun lade dig kalde metoder, som dens type ( Cowklassen) har.

Indsnævrende type konvertering
Cow cow = new Whale();
if (cow instanceof Whale)
{
   Whale whale = (Whale) cow;
}
Klassisk indsnævringskonvertering: Du skal tilføje et typetjek og en cast-operatør.
Variablen Cow cowgemmer en reference til et Whaleobjekt.
Vi bekræfter, at dette er tilfældet , og udfører derefter en (indsnævrende) typekonvertering. Eller som det også kaldes:
en type cast
.

Cow cow = new Cow();
Whale whale = (Whale) cow; // Exception
Du kan indsnævre en referencetype uden at kontrollere objektets type.
Hvis cowvariablen refererer til et objekt, der ikke er et Whale, InvalidClassCastExceptionvil der blive genereret en.


3. Kald den oprindelige metode: supernøgleordet

Når vi tilsidesætter en forældreklasses metode, vil vi nogle gange i stedet for at erstatte den med vores egen, kun supplere den lidt.

Det ville være fedt, hvis vi kunne moderklassens metode i vores metode, og derefter udføre noget af vores egen kode. Eller måske først eksekvere vores egen kode og derefter kalde forældreklassens metode.

Og Java tillader os netop det. For at kalde en metode for den overordnede klasse skal du gøre 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 værdien af Pi​​være større end 6! Selvfølgelig laver vi sjov, men dette eksempel viser, hvordan det hele kan fungere.

Her er et par flere eksempler for at præcisere tingene lidt:

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();
}
Skærmoutput vil være:
I'm a white whale
This is incorrect: I'm a cow
I'm a whale

Det her er hårde ting. Helt ærligt, det er en af ​​de sværeste ting i OOP . Når det er sagt, skal du vide og forstå det.