1. Typecasting

Variabler som lagrar referenstyper (klasser) kan också konverteras till olika typer. Men detta fungerar bara inom en enda typhierarki. Låt oss titta på ett enkelt exempel. Anta att vi har följande klasshierarki, där klasserna nedan ärver klasserna ovan.

Typecasting

Typecasting av såväl referenstyper som primitiva kategoriseras också som antingen breddning och avsmalning.

Vi ser att Cat-klassen ärver Pet-klassen och Pet-klassen i sin tur ärver Animal-klassen.

Om vi ​​skriver kod så här:

Animal kitten = new Cat();

Detta är en omvandling av breddande typ . Det kallas också en implicit rollbesättning. Vi har utökat kattreferensen så att den nu hänvisar till ett Cat- objekt. Med en typkonvertering som denna kommer vi inte att kunna använda kattungereferensen för att anropa metoder som finns i Cat -klassen men frånvarande i Animal- klassen.

En minskande konvertering (eller explicit roll) sker i motsatt riktning:

Cat cat = (Cat) kitten;

Vi angav uttryckligen att vi vill gjuta referensen lagrad i kattungevariabeln ( vars typ är Animal ) till Cat -typen.



2. Kontrollera typen av ett objekt

Men du måste vara väldigt försiktig här. Om du gör så här:

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

Kompilatorn tillåter denna kod, men det kommer att uppstå ett fel när programmet körs! JVM kommer att göra ett undantag:

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

Referenser till ett Cat- objekt kan endast lagras i variabler vars typ är en förfader av Cat-klassen: Pet, Animal eller Object.

Varför är det så?

Den relevanta punkten här är att en objektreferens används för att referera till metoderna och variablerna för det objektet . Och det blir inga problem om vi använder en Animal-variabel för att lagra en referens till ett Cat-objekt: Cat-typen har alltid variabler och metoder av Animal-typen – den ärvde dem!

Men om JVM tillät oss att lagra en referens till ett Cat-objekt i en Wolf-variabel, så kan vi ha en situation där vi kan försöka använda grayWolf-variabeln för att anropa en metod som inte finns i Cat-objektet lagrat i den variabeln . Det är därför detta arrangemang inte är tillåtet.

Java har en speciell instanceofoperator som låter dig kontrollera om ett objekt är av en viss typ och därför kan lagras i en variabel av en viss typ. Det ser ganska enkelt ut:

variable instanceof Type

Exempel:

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

Den här koden kommer inte att orsaka fel – inte ens under körning.

Här är några fler exempel som illustrerar situationen:

Breddande typkonvertering Beskrivning
Cow cow = new Whale();

Detta är en klassisk breddningskonvertering — ingen typkonverteringsoperatör krävs. Nu Cowkan bara de metoder som definieras i klassen anropas på Whaleobjektet.

cowvariabeln låter kompilatorn dig bara anropa metoder som dess typ ( Cowklassen) har.

Konvertering av avsmalnande typ
Cow cow = new Whale();
if (cow instanceof Whale)
{
   Whale whale = (Whale) cow;
}
Klassisk avsmalningskonvertering: Du måste lägga till en typkontroll och en rolloperator.
Variabeln Cow cowlagrar en referens till ett Whaleobjekt.
Vi verifierar att så är fallet och utför sedan en (avsmalnande) typkonvertering. Eller som det också kallas:
en typ cast
.

Cow cow = new Cow();
Whale whale = (Whale) cow; // Exception
Du kan begränsa en referenstyp utan att kontrollera objektets typ.
Om cowvariabeln hänvisar till ett objekt som inte är en , kommer Whaleen InvalidClassCastExceptionatt genereras.


3. Anropa den ursprungliga metoden: supernyckelordet

När vi åsidosätter en föräldraklasss metod, ibland istället för att ersätta den med vår egen, vill vi bara komplettera den något.

Det skulle vara coolt om vi kunde moderklassens metod i vår metod, och sedan exekvera lite av vår egen kod. Eller kanske först exekvera vår egen kod och sedan anropa föräldraklassens metod.

Och Java låter oss göra just det. För att anropa en metod för den överordnade klassen, gör så här:

super.method(arguments);

Exempel:

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ärdet på Pivara större än 6! Naturligtvis skämtar vi, men det här exemplet visar hur allt detta kan fungera.

Här är ytterligare ett par exempel för att förtydliga saker och ting lite:

Koda Beskrivning
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");
   }
}
Cowoch Whaleklasser
public static void main(String[] args)
{
   Whale whale = new Whale();
   whale.printAll();
}
Skärmutgången blir:
I'm a white whale
This is incorrect: I'm a cow
I'm a whale

Det här är svåra grejer. Ärligt talat, det är en av de svåraste sakerna i OOP . Som sagt, du behöver veta och förstå det.