"Amigo, mahilig ka ba sa mga balyena?"

"Whales? Nope, never heard of them."

"Parang baka, mas malaki lang at lumalangoy. Incidentally, ang mga whale came from cows. Uh, or at least they share a common ancestor. It doesn't matter."

Polymorphism at overriding - 1

"Makinig ka. Gusto kong sabihin sa iyo ang tungkol sa isa pang napakalakas na tool ng OOP: polymorphism . Mayroon itong apat na feature."

1) Pamamaraan override.

Isipin na nagsulat ka ng isang "Baka" na klase para sa isang laro. Mayroon itong maraming mga variable at pamamaraan ng miyembro. Ang mga bagay ng klase na ito ay maaaring gumawa ng iba't ibang bagay: maglakad, kumain, matulog. Tumutunog din ang mga baka kapag naglalakad. Sabihin nating naipatupad mo ang lahat sa klase hanggang sa pinakamaliit na detalye.

Polymorphism at overriding - 2

Pagkatapos ay biglang sinabi ng customer na gusto niyang ilabas ang isang bagong antas ng laro, kung saan ang lahat ng mga aksyon ay nagaganap sa dagat, at ang pangunahing karakter ay isang balyena.

Sinimulan mong idisenyo ang klase ng Whale at napagtanto mo na ito ay bahagyang naiiba kaysa sa klase ng Cow. Ang parehong mga klase ay gumagamit ng halos kaparehong lohika, at nagpasya kang gumamit ng mana.

Ang klase ng Baka ay angkop na angkop na maging parent class: mayroon na itong lahat ng kinakailangang variable at pamamaraan. Ang kailangan mo lang gawin ay idagdag ang kakayahan ng balyena na lumangoy. Ngunit may problema: ang iyong balyena ay may mga binti, sungay, at kampana. Pagkatapos ng lahat, ipinapatupad ng klase ng Baka ang pagpapaandar na ito. Ano ang kaya mong gawin?

Polymorphism at overriding - 3

Ang paraan ng pag-override ay dumating upang iligtas. Kung magmana tayo ng isang pamamaraan na hindi nagagawa nang eksakto kung ano ang kailangan natin sa ating bagong klase, maaari nating palitan ang pamamaraan ng isa pa.

Polymorphism at overriding - 4

Paano ito ginagawa? Sa aming descendant class, idinedeklara namin ang method na gusto naming baguhin (na may parehong method signature tulad ng sa parent class) . Pagkatapos ay sumulat kami ng bagong code para sa pamamaraan. Ayan yun. Para bang ang lumang pamamaraan ng parent class ay hindi umiiral.

Narito kung paano ito gumagana:

Code Paglalarawan
class Cow
{
public void printColor()
{
System.out.println("I'm white");
}
public void printName()
{
System.out.println("I'm a cow");
}
}class Whale extends Cow
{
public void printName()
{
System.out.println("I'm a whale");
}
}
Dito ay tinukoy natin ang dalawang klase:  Cow at  WhaleWhalenamamana  Cow.

Ino-override ng  Whale klase ang  printName();pamamaraan.

public static void main(String[] args)
{
Cow cow = new Cow();
cow.printName();
}
Ang code na ito ay nagpapakita ng " Ako ay isang baka " sa screen.
public static void main(String[] args)
{
Whale whale = new Whale();
whale.printName();
}
Ipinapakita ng code na ito ang " I'm a whale " sa screen

Pagkatapos nitong magmana Cowat mag-override printName, ang Whaleklase ay talagang mayroong sumusunod na data at pamamaraan:

Code Paglalarawan
class Whale
{
public void printColor()
{
System.out.println("I'm white");
}
public void printName()
{
System.out.println("I'm a whale");
}
}
Wala kaming alam tungkol sa anumang lumang pamamaraan.

"Sa totoo lang, iyon ang inaasahan ko."

2) Ngunit hindi lang iyon.

"Ipagpalagay na ang  Cow klase ay may  printAll, pamamaraan na tumatawag sa dalawang iba pang mga pamamaraan. Kung gayon ang code ay gagana nang ganito:"

Ipapakita sa screen ang:
Ako ay puti,
ako ay isang balyena

Code Paglalarawan
class Cow
{
public void printAll()
{
printColor();
printName();
}
public void printColor()
{
System.out.println("I'm white");
}
public void printName()
{
System.out.println("I'm a cow");
}
}

class Whale extends Cow
{
public void printName()
{
System.out.println("I'm a whale");
}
}
public static void main(String[] args)
{
Whale whale = new Whale();
whale.printAll();
}
Ipapakita sa screen ang:
Ako ay puti,
ako ay isang balyena

Tandaan na kapag ang pamamaraan ng printAll () ng klase ng Baka ay tinawag sa isang bagay na Balyena, ang paraan ng printName() ng Balyena ang gagamitin, hindi ang paraan ng Baka.

Ang mahalagang bagay ay hindi ang klase kung saan nakasulat ang pamamaraan, ngunit sa halip ay uri (klase) ng bagay kung saan tinawag ang pamamaraan.

"Nakita ko."

"Maaari ka lang magmana at mag-override ng mga non-static na pamamaraan. Ang mga static na pamamaraan ay hindi namamana at samakatuwid ay hindi maaaring ma-override."

Narito kung ano ang hitsura ng klase ng Whale pagkatapos naming ilapat ang mana at i-override ang mga pamamaraan:

Code Paglalarawan
class Whale
{
public void printAll()
{
printColor();
printName();
}
public void printColor()
{
System.out.println("I'm white");
}
public void printName()
{
System.out.println("I'm a whale");
}
}
Narito kung ano ang hitsura ng klase ng Whale pagkatapos naming ilapat ang mana at i-override ang pamamaraan. Wala kaming alam tungkol sa anumang lumang printNamepamamaraan.

3) Uri ng paghahagis.

Narito ang isang mas kawili-wiling punto. Dahil ang isang klase ay nagmamana ng lahat ng mga pamamaraan at data ng kanyang parent class, ang isang object ng class na ito ay maaaring i-reference ng mga variable ng parent class (at ang parent ng parent, atbp., hanggang sa Object class). Isaalang-alang ang halimbawang ito:

Code Paglalarawan
public static void main(String[] args)
{
Whale whale = new Whale();
whale.printColor();
}
Ipapakita sa screen ang:
Puti ako.
public static void main(String[] args)
{
Cow cow = new Whale();
cow.printColor();
}
Ipapakita sa screen ang:
Puti ako.
public static void main(String[] args)
{
Object o = new Whale();
System.out.println(o.toString());
}
Ipapakita sa screen ang:
Whale@da435a.
Ang toString() method ay minana mula sa Object class.

"Good stuff. Pero bakit kailangan mo ito?"

"Ito ay isang mahalagang tampok. Malalaman mo sa ibang pagkakataon na ito ay napaka, napakahalaga."

4) Late binding (dynamic dispatch).

Narito ang hitsura nito:

Code Paglalarawan
public static void main(String[] args)
{
Whale whale = new Whale();
whale.printName();
}
Ipapakita sa screen ang:
Ako ay isang balyena.
public static void main(String[] args)
{
Cow cow = new Whale();
cow.printName();
}
Ipapakita sa screen ang:
Ako ay isang balyena.

Tandaan na hindi ang uri ng variable ang tumutukoy kung aling partikular na paraan ng printName ang tawag namin (sa klase ng Cow o Whale), ngunit sa halip ay ang uri ng bagay na tinutukoy ng variable.

Ang Cow variable ay nag-iimbak ng reference sa isang Whale object, at ang printName method na tinukoy sa Whale class ay tatawagin.

"Well, hindi nila idinagdag iyon para sa kalinawan."

"Oo, hindi gaanong halata. Tandaan ang mahalagang panuntunang ito:"

Ang hanay ng mga pamamaraan na maaari mong tawagan sa isang variable ay tinutukoy ng uri ng variable. Ngunit kung aling partikular na pamamaraan/implementasyon ang matatawag ay tinutukoy ng uri/klase ng bagay na isinangguni ng variable.

"Susubukan ko."

"Patuloy mong tatakbo ito, kaya't mabilis mong mauunawaan ito at hinding hindi makakalimutan."

5) Uri ng paghahagis.

Iba ang paggana ng pag-cast para sa mga uri ng sanggunian, ibig sabihin, mga klase, kaysa sa mga primitive na uri. Gayunpaman, nalalapat din ang pagpapalawak at pagpapaliit ng mga conversion sa mga uri ng sanggunian. Isaalang-alang ang halimbawang ito:

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

Isang klasikong pagpapalawak ng conversion. Ngayon ay maaari ka lamang tumawag sa mga pamamaraan na tinukoy sa klase ng Baka sa bagay na Balyena.

Hahayaan ka ng compiler na gamitin ang variable ng baka upang tawagan ang mga pamamaraang iyon na tinukoy ng uri ng Baka.

Pagpapaliit ng conversion Paglalarawan
Cow cow = new Whale();
if (cow instanceof Whale)
{
Whale whale = (Whale) cow;
}
Isang klasikong pagpapaliit ng conversion na may uri ng check. Ang variable ng baka ng uri ng Cow ay nag-iimbak ng sanggunian sa isang bagay na Balyena.
Sinusuri namin na ito ang kaso , at pagkatapos ay isagawa ang (pagpapalawak) uri ng conversion. Ito ay tinatawag ding type casting .
Cow cow = new Cow();
Whale whale = (Whale) cow; //exception
Maaari ka ring magsagawa ng pagpapaliit ng conversion ng isang uri ng sanggunian nang hindi sinusuri ang uri ng bagay.
Sa kasong ito, kung ang variable ng baka ay tumuturo sa isang bagay maliban sa isang Whale object, isang exception (InvalidClassCastException) ang itatapon.

6) At ngayon para sa isang masarap. Pagtawag sa orihinal na pamamaraan.

Minsan kapag na-override ang isang minanang pamamaraan ay hindi mo nais na ganap na palitan ito. Minsan gusto mo lang magdagdag ng kaunti dito.

Sa kasong ito, gusto mo talagang tawagan ang code ng bagong pamamaraan sa parehong paraan, ngunit sa base class. At hinahayaan ka ng Java na gawin ito. Ito ay kung paano ito ginagawa:  super.method().

Narito ang ilang halimbawa:

Code Paglalarawan
class Cow
{
public void printAll()
{
printColor();
printName();
}
public void printColor()
{
System.out.println("I'm white");
}
public void printName()
{
System.out.println("I'm a cow");
}
}

class Whale extends Cow
{
public void printName()
{
System.out.print("This is false: ");
super.printName();

System.out.println("I'm a whale");
}
}
public static void main(String[] args)
{
Whale whale = new Whale();
whale.printAll();
}
Ipapakita sa screen ang:
Puti ako
This is false: I'm a cow
I'm a whale

"Hmm. Well, that was some lesson. Halos matunaw ang tenga ko sa robot."

"Oo, hindi ito simpleng bagay. Ito ang ilan sa pinakamahirap na materyal na makakaharap mo. Nangako ang propesor na magbibigay ng mga link sa mga materyales mula sa ibang mga may-akda, upang kung may hindi ka pa naiintindihan, maaari mong punan ang gaps."