Saskaņā ar leģendu Venkat Subramaniam polimorfisms ir vissvarīgākais jēdziens objektorientētajā programmēšanā. Polimorfisms- vai objekta spēja veikt specializētas darbības, pamatojoties uz tā tipu, padara Java kodu elastīgu. Dizaina modeļos, piemēram, Command, Observer, Decorator, Strategy un daudzos citos, ko izveidojusi Gang Of Four, visi tiek izmantoti kāda veida polimorfisms. Šīs koncepcijas apguve ievērojami uzlabo jūsu spēju domāt, izmantojot risinājumus programmēšanas izaicinājumiem.
Iegūstiet kodu
Jūs varat iegūt šī izaicinājuma avota kodu un veikt savus testus šeit: //github.com/rafadelnero/javaworld-challengers
Saskarnes un iedzimtība polimorfismā
Ar šo Java Challenger mēs koncentrējamies uz polimorfisma un mantojuma attiecībām. Galvenais, kas jāpatur prātā, ir tas, ka polimorfisms prasa mantojums vai saskarnes ieviešana. To var redzēt zemāk esošajā piemērā, kurā ir hercogs un Jugijs:
publiskā abstraktā klase JavaMascot {public abstract void executeAction (); } public class Duke paplašina JavaMascot {@Override public void executeAction () {System.out.println ("Punch!"); }} public class Juggy paplašina JavaMascot {@Override public void executeAction () {System.out.println ("Fly!"); }} public class JavaMascotTest {public static void main (String ... args) {JavaMascot dukeMascot = new Duke (); JavaMascot juggyMascot = jauns Juggy (); dukeMascot.executeAction (); juggyMascot.executeAction (); }}
Šī koda izvade būs:
Perforators! Lido!
To īpašās ieviešanas dēļ abi Hercogs
un Juggy
Tiks izpildītas.
Vai metode pārslogo polimorfismu?
Daudzi programmētāji ir neizpratnē par polimorfisma saistību ar metodes ignorēšanu un metodes pārslodzi. Faktiski patiesais polimorfisms ir tikai svarīgākā metode. Pārslodzes gadījumā tiek izmantots tās pašas metodes nosaukums, taču parametri ir atšķirīgi. Polimorfisms ir plašs termins, tāpēc par šo tēmu vienmēr notiks diskusijas.
Kāds ir polimorfisma mērķis?
Polimorfisma izmantošanas lielā priekšrocība un mērķis ir atdalīt klienta klasi no ieviešanas koda. Tā vietā, lai klienta klase būtu kodēta, tā saņem ieviešanu, lai veiktu nepieciešamo darbību. Tādā veidā klientu klase zina tikai pietiekami daudz, lai izpildītu savas darbības, kas ir brīvas savienošanas piemērs.
Lai labāk izprastu polimorfisma mērķi, ieskatieties SweetCreator
:
publiskā abstraktā klase SweetProducer {public abstract void producSweet (); } public class CakeProducer paplašina SweetProducer {@Override public void producSweet () {System.out.println ("Kūka ražota"); }} sabiedrības klases ChocolateProducer paplašina SweetProducer {@Override public void producSweet () {System.out.println ("Šokolāde ražota"); }} public class CookieProducer paplašina SweetProducer {@Override public void producSweet () {System.out.println ("Sīkdatne ražota"); }} publiskā klase SweetCreator {private List sweetProducer; public SweetCreator (List sweetProducer) {this.sweetProducer = sweetProducer; } public void createSweets () {sweetProducer.forEach (sweet -> sweet.produceSweet ()); }} public class SweetCreatorTest {public static void main (String ... args) {SweetCreator sweetCreator = new SweetCreator (Arrays.asList (new CakeProducer (), new ChocolateProducer (), new CookieProducer ())); sweetCreator.createSweets (); }}
Šajā piemērā jūs varat redzēt, ka SweetCreator
klase zina tikai
SweetProducer
klasē. Tā nezina katra īstenošanu Salds
. Šī nošķiršana dod mums iespēju atjaunot un atkārtoti izmantot mūsu klases, un tas padara kodu daudz vieglāk uzturamu. Veidojot kodu, vienmēr meklējiet veidus, kā padarīt to pēc iespējas elastīgāku un uzturamāku. polimorfisms ir ļoti spēcīgs paņēmiens, ko izmantot šiem mērķiem.
Padoms: @ Pārvarēt
anotācija uzliek programmētājam pienākumu izmantot to pašu metodes parakstu, kas ir jāpārņem. Ja metode netiek ignorēta, radīsies kompilācijas kļūda.
Kovariāna atdeves veidi metodes ignorēšanā
Ir iespējams mainīt ignorētās metodes atgriešanas veidu, ja tas ir kovariants. A kovariāna tips būtībā ir atgriešanās veida apakšklase. Apsveriet piemēru:
publiskā abstraktā klase JavaMascot {abstraktā JavaMascot getMascot (); } public class Duke paplašina JavaMascot {@Orride Duke getMascot () {return new Duke (); }}
Tā kā Hercogs
ir JavaMascot
, mēs varam mainīt atgriešanās veidu, ignorējot.
Polimorfisms ar Java pamatklasēm
Java pamatklasēs mēs visu laiku izmantojam polimorfismu. Viens ļoti vienkāršs piemērs ir tas, kad mēs veicam ArrayList
klase, kas deklarēSaraksts
interfeiss kā tips:
Sarakstu saraksts = new ArrayList ();
Lai ietu tālāk, apsveriet šo koda paraugu, izmantojot Java kolekciju API bez polimorfisms:
public class ListActionWithoutPolymorphism {// Piemērs bez polimorfisma void executeVectorActions (Vector vector) {/ * Koda atkārtošana šeit * /} void executeArrayListActions (ArrayList arrayList) {/ * Koda atkārtošana šeit * /} void executeLinkedListActions * LinkedList {LinkedList here * /} void executeCopyOnWriteArrayListActions (CopyOnWriteArrayList copyOnWriteArrayList) {/ * Koda atkārtošana šeit * /}} public class ListActionInvokerWithoutPolymorphism {listAction.executeVectorActions (new Vector ()); listAction.executeArrayListActions (jauns ArrayList ()); listAction.executeLinkedListActions (jauns LinkedList ()); listAction.executeCopyOnWriteArrayListActions (jauns CopyOnWriteArrayList ()); }
Neglīts kods, vai ne? Iedomājieties, kā mēģināt to uzturēt! Tagad aplūkojiet to pašu piemēru ar polimorfisms:
public static void main (String ... polymorphism) {ListAction listAction = new ListAction (); listAction.executeListActions (); } public class ListAction {void executeListActions (List list) {// Izpildīt darbības ar dažādiem sarakstiem}} public class ListActionInvoker {public static void main (String ... masterPolymorphism) {ListAction listAction = new ListAction (); listAction.executeListActions (jauns Vector ()); listAction.executeListActions (jauns ArrayList ()); listAction.executeListActions (jauns LinkedList ()); listAction.executeListActions (jauns CopyOnWriteArrayList ()); }}
Polimorfisma priekšrocība ir elastība un paplašināmība. Tā vietā, lai izveidotu vairākas dažādas metodes, mēs varam deklarēt tikai vienu metodi, kas saņem vispārīgo Saraksts
tips.
Specifisku metožu izsaukšana polimorfās metodes izsaukumā
Polimorfā izsaukumā ir iespējams atsaukties uz noteiktām metodēm, taču tas tiek darīts par elastības cenu. Lūk, piemērs:
publiskā abstraktā klase MetalGearCharacter {abstract void useWeapon (String ierocis); } publiskā klase BigBoss paplašina MetalGearCharacter {@Override void useWeapon (String ierocis) {System.out.println ("Big Boss izmanto ieroci +); } void giveOrderToTheArmy (String orderMessage) {System.out.println (orderMessage); }} publiskā klase SolidSnake paplašina MetalGearCharacter {void useWeapon (String ierocis) {System.out.println ("Solid Snake izmanto" ieroci +); }} public class UseSpecificMethod {public static void executeActionWith (MetalGearCharacter metalGearCharacter) {metalGearCharacter.useWeapon ("SOCOM"); // Zemāk esošā rinda nedarbosies // metalGearCharacter.giveOrderToTheArmy ("Uzbrukums!"); if (metalGearCharacter instance of BigBoss) {((BigBoss) metalGearCharacter) .giveOrderToTheArmy ("Uzbrukums!"); }} public static void main (String ... specificPolymorphismInvocation) {executeActionWith (new SolidSnake ()); executeActionWith (jauns BigBoss ()); }}
Šeit izmantotā tehnika ir liešanavai apzināti mainot objekta tipu izpildlaikā.
Ņemiet vērā, ka ir iespējams izmantot noteiktu metodi tikai nododot vispārīgo tipu konkrētajam tipam. Laba līdzība būtu skaidri teikt sastādītājam: “Hei, es zinu, ko es šeit daru, tāpēc es nodošu objektu konkrētam tipam un izmantoju noteiktu metodi.”
Atsaucoties uz iepriekš minēto piemēru, ir svarīgs iemesls, kāpēc kompilators atsakās pieņemt noteiktu metodes izsaukumu: klasi, kas tiek nodota, var SolidSnake
. Šajā gadījumā kompilatoram nav iespējas nodrošināt ikvienu MetalGearRaksturs
ir giveOrderToTheArmy
deklarētā metode.
The instanceof
rezervēts atslēgvārds
Pievērsiet uzmanību rezervētajam vārdam instanceof
. Pirms izmantot konkrēto metodi, mēs esam vaicājuši, vai MetalGearRaksturs
ir “instanceof
” Lielais boss
. Ja tas nebija a Lielais boss
mēs saņemtu šādu ziņojumu par izņēmumu:
Izņēmums pavedienā "main" java.lang.ClassCastException: com.javaworld.javachallengers.polymorphism.specificinvocation.SolidSnake nevar nodot vietnei com.javaworld.javachallengers.polymorphism.specificinvocation.BigBoss
The super
rezervēts atslēgvārds
Ko darīt, ja mēs gribētu atsaukties uz atribūtu vai metodi no Java superklases? Šajā gadījumā mēs varētu izmantot super
rezervēts vārds. Piemēram:
publiskā klase JavaMascot {void executeAction () {System.out.println ("Java talismans gatavojas izpildīt darbību!"); }} public class Duke paplašina JavaMascot {@Override void executeAction () {super.executeAction (); System.out.println ("Hercogs gatavojas iesist!"); } public static void main (String ... superReservedWord) {new Duke (). executeAction (); }}
Izmantojot rezervēto vārdu super
iekšā Hercogs
’S izpildītAction
metode izsauc superklases metodi. Pēc tam mēs izpildām konkrēto darbību no Hercogs
. Tāpēc zemāk redzamajā izvadē mēs varam redzēt abus ziņojumus:
Java talismans gatavojas veikt darbību! Hercogs gatavojas iesist!
Pieņem polimorfisma izaicinājumu!
Izmēģināsim to, ko esat iemācījušies par polimorfismu un mantojumu. Šajā izaicinājumā jums tiek dota nedaudz metožu no Meta Groeninga Simpsoniem, un jūsu uzdevums ir secināt, kāds būs katras klases iznākums. Lai sāktu, rūpīgi analizējiet šo kodu:
publiskā klase Polimorfisma izaicinājums {statiskā abstraktā klase Simpsons {void talk () {System.out.println ("Simpsons!"); } aizsargāta tukša palaidnība (virknes palaidnība) {System.out.println (palaidnība); }} statiskā klase Barts pagarina Simpsonu {Stīgu palaidnība; Bārts (stīgu palaidnība) {this. palaidnība = palaidnība; } protected void talk () {System.out.println ("Ēd manus šortus!"); } aizsargāta tukša palaidnība () {super.prank (palaidnība); System.out.println ("Nokaut Homeru uz leju"); }} statiskā klase Liza pagarina Simpsonu {void talk (String toMe) {System.out.println ("I love Sax!"); }} public static void main (String ... doYourBest) {new Lisa (). talk ("Sax :)"); Simpsons simpsons = jauns Barts ("D'oh"); simpson.talk (); Lisa lisa = jauna Lisa (); lisa.talk (); ((Bart) simpson). Palaidnība (); }}
Ko tu domā? Kāda būs galīgā produkcija? Lai to noskaidrotu, neizmantojiet IDE! Punkts ir uzlabot savas koda analīzes prasmes, tāpēc mēģiniet pats noteikt rezultātu.
Izvēlieties atbildi, un tālāk varēsiet atrast pareizo atbildi.
A) Es mīlu Saksu! D'oh Simpson! D'oh B) Sax :) Ēd manus šortus! Es mīlu Saksu! D'oh Knock Homer down C) Sax :) D'oh Simpson! Nokauj Homeru uz leju D) Es mīlu Saksu! Ēd manus šortus! Simpson! D'oh nokauj Homēru
Kas tikko notika? Izpratne par polimorfismu
Šādas metodes izsaukšanai:
jaunā Liza (). saruna ("Sax :)");
izeja būs “Es mīlu Saksu!
”Tas ir tāpēc, ka mēs ejam garām Stīga
uz metodi un Liza
ir metode.
Nākamajam aicinājumam:
Simpsons simpsons = jauns Barts ("D'oh");
simpson.talk ();
Rezultāts būs "Ēd manus šortus!
"Tas ir tāpēc, ka mēs veicam Simpsons
ierakstiet ar Bārts
.
Tagad pārbaudiet šo, kas ir nedaudz sarežģītāk:
Lisa lisa = jauna Lisa (); lisa.talk ();
Šeit mēs izmantojam metodes pārslodzi ar mantojumu. Mēs neko nepievienojam sarunu metodei, tāpēc Simpsons
runāt
metode tiek izmantota. Šajā gadījumā izeja būs:
- Simpson!
Šeit ir vēl viens:
((Bart) simpson). Palaidnība ();
Šajā gadījumā palaidnība Stīga
tika nodota, kad mēs instantiated Bārts
klase ar jaunais Barts ("D'oh");
. Šajā gadījumā vispirms super.prank
metode, kam sekos specifiskā palaidnība
metode no Bārts
. Rezultāts būs:
"D'oh" "Notrieciet Homēru"
Video izaicinājums! Java polimorfisma un mantojuma atkļūdošana
Atkļūdošana ir viens no vienkāršākajiem veidiem, kā pilnībā absorbēt programmēšanas koncepcijas, vienlaikus uzlabojot arī kodu. Šajā video jūs varat sekot līdzi, kamēr es atkļūdoju un izskaidroju Java polimorfisma izaicinājumu:
Bieži pieļautās kļūdas ar polimorfismu
Tā ir izplatīta kļūda, domājot, ka ir iespējams atsaukties uz noteiktu metodi, neizmantojot liešanu.
Vēl viena kļūda ir neziņa, kāda metode tiks izmantota, polimorfiski klasificējot klasi. Atcerieties, ka izmantotā metode ir izveidotās instances metode.
Atcerieties arī, ka metodes ignorēšana nav metodes pārslodze.
Ja parametri atšķiras, metodi nav iespējams ignorēt. Tā ir iespējams lai mainītu ignorētās metodes atgriešanas tipu, ja atgriešanas veids ir superklases metodes apakšklase.
Kas jāatceras par polimorfismu
- Izveidotais gadījums noteiks, kāda metode tiks izmantota, izmantojot polimorfismu.
- The
@ Pārvarēt
anotācija uzliek programmētājam pienākumu izmantot ignorētu metodi; ja nē, būs sastādītāja kļūda. - Polimorfismu var izmantot ar parastām klasēm, abstraktām klasēm un saskarnēm.
- Lielākā daļa dizaina modeļu ir atkarīgi no kāda polimorfisma veida.
- Vienīgais veids, kā izmantot polimorfā apakšklasē noteiktu metodi, ir liešana.
- Izmantojot polimorfismu, ir iespējams izveidot spēcīgu koda struktūru.
- Palaidiet savus testus. To darot, jūs varēsiet apgūt šo spēcīgo koncepciju!
Atbildes atslēga
Atbilde šim Java izaicinātājam ir D. Rezultāts būtu:
Es mīlu Saksu! Ēd manus šortus! Simpson! D'oh nokauj Homēru
Šo stāstu "Polimorfisms un mantošana Java" sākotnēji publicēja JavaWorld.