1. Typecasting

Ang mga variable na nag-iimbak ng mga uri ng sanggunian (mga klase) ay maaari ding i-convert sa iba't ibang uri. Ngunit ito ay gumagana lamang sa loob ng iisang uri ng hierarchy. Tingnan natin ang isang simpleng halimbawa. Ipagpalagay na mayroon tayong sumusunod na hierarchy ng klase, kung saan ang mga klase sa ibaba ay nagmamana ng mga klase sa itaas.

Typecasting

Ang pag-typecast ng mga uri ng sanggunian pati na rin ang mga primitive ay ikinategorya din bilang alinman sa pagpapalawak at pagpapaliit.

Nakikita natin na ang klase ng Cat ay nagmamana ng klase ng Alagang Hayop, at ang klase ng Alagang Hayop, naman, ay nagmamana ng klase ng Hayop.

Kung sumulat tayo ng code tulad nito:

Animal kitten = new Cat();

Ito ay isang pagpapalawak ng uri ng conversion . Tinatawag din itong implicit cast. Pinalawak namin ang sanggunian ng pusa upang tumukoy ito ngayon sa isang bagay na Pusa . Sa uri ng conversion na tulad nito, hindi namin magagamit ang kuting na reference sa mga pamamaraan ng pagtawag na nasa klase ng Cat ngunit wala sa klase ng Animal .

Ang isang makitid na conversion (o tahasang cast) ay nangyayari sa kabaligtaran na direksyon:

Cat cat = (Cat) kitten;

Tahasang ipinahiwatig na gusto naming i-cast ang reference na nakaimbak sa kitten variable (na ang uri ay Animal ) sa uri ng Pusa .



2. Pagsusuri sa uri ng isang bagay

Ngunit kailangan mong maging maingat dito. Kung gagawin mo ito:

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

Papayagan ng compiler ang code na ito, ngunit magkakaroon ng error kapag tumatakbo ang program! Ang JVM ay magtapon ng isang pagbubukod:

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

Ang mga sanggunian sa isang bagay na Pusa ay maaari lamang iimbak sa mga variable na ang uri ay isang ninuno ng klase ng Pusa: Alagang Hayop, Hayop, o Bagay.

Bakit ganon?

Ang nauugnay na punto dito ay ang isang object reference ay ginagamit upang sumangguni sa mga pamamaraan at variable ng object na iyon . At hindi magkakaroon ng anumang problema kung gagamit tayo ng Animal variable upang mag-imbak ng reference sa isang Cat object: ang uri ng Cat ay palaging may mga variable at pamamaraan ng Animal type — namana nito ang mga ito!

Ngunit kung pinahintulutan kami ng JVM na mag-imbak ng isang reference sa isang Cat object sa isang Wolf variable, kung gayon maaari kaming magkaroon ng isang sitwasyon kung saan maaari naming subukang gamitin ang grayWolf variable upang tumawag sa isang paraan na wala sa Cat object na nakaimbak sa variable na iyon. . Kaya naman bawal ang ganitong arrangement.

Ang Java ay may isang espesyal instanceofna operator na hinahayaan kang suriin kung ang isang bagay ay nasa isang tiyak na uri at samakatuwid ay maaaring maimbak sa isang variable ng isang tiyak na uri. Mukhang medyo simple:

variable instanceof Type

Halimbawa:

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

Ang code na ito ay hindi magdudulot ng mga error — kahit na sa runtime.

Narito ang ilan pang mga halimbawa na naglalarawan ng sitwasyon:

Pagpapalawak ng uri ng conversion Paglalarawan
Cow cow = new Whale();

Ito ay isang klasikong pagpapalawak ng conversion — walang kinakailangang operator ng uri ng conversion. Ngayon lamang ang mga pamamaraan na tinukoy sa Cowklase ay maaaring tawagan sa Whalebagay.

Sa cowvariable , hahayaan ka lang ng compiler na tumawag sa mga pamamaraan na Cowmayroon ang uri nito (ang klase).

Narrowing type conversion
Cow cow = new Whale();
if (cow instanceof Whale)
{
   Whale whale = (Whale) cow;
}
Classic na pagpapaliit ng conversion: Kailangan mong magdagdag ng type check at cast operator.
Ang Cow cowvariable ay nag-iimbak ng isang sanggunian sa isang Whalebagay.
Bine-verify namin na ito ang kaso , at pagkatapos ay magsagawa ng (narrowing) uri ng conversion. O kung tawagin din:
isang uri ng cast
.

Cow cow = new Cow();
Whale whale = (Whale) cow; // Exception
Maaari mong paliitin ang isang uri ng sanggunian nang hindi sinusuri ang uri ng bagay.
Kung ang cowvariable ay tumutukoy sa isang bagay na hindi isang Whale, pagkatapos ay isang InvalidClassCastExceptionay bubuo.


3. Pagtawag sa orihinal na paraan: ang superkeyword

Kapag na-override ang paraan ng parent class, minsan sa halip na palitan ito ng sarili namin, gusto lang namin itong dagdagan nang bahagya.

Magiging cool na kung maaari naming ang paraan ng parent class sa aming pamamaraan, at pagkatapos ay isagawa ang ilan sa aming sariling code. O marahil ay isagawa muna ang sarili nating code, at pagkatapos ay tawagan ang pamamaraan ng parent class.

At hinahayaan tayo ng Java na gawin iyon. Upang tumawag ng paraan ng parent class, gawin ito:

super.method(arguments);

Mga halimbawa:

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

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

Sa panahon ng digmaan, ang halaga ng Piay maaaring higit sa 6! Siyempre, nagbibiro kami, ngunit ipinapakita ng halimbawang ito kung paano gagana ang lahat ng ito.

Narito ang ilang higit pang mga halimbawa upang linawin ang mga bagay nang kaunti:

Code Paglalarawan
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");
   }
}
Cowat Whalemga klase
public static void main(String[] args)
{
   Whale whale = new Whale();
   whale.printAll();
}
Ang output ng screen ay magiging:
I'm a white whale
This is incorrect: I'm a cow
I'm a whale

Ito ay mahirap na bagay. Sa totoo lang, isa ito sa pinakamahirap na bagay sa OOP . Sabi nga, kailangan mong malaman at maunawaan ito.