I Java er tilsidesættelse en funktion, der tillader en underklasse eller underklasse at levere en specifik implementering af en metode, der allerede er leveret af en af dens superklasser eller overordnede klasser. Når en metode i en underklasse har det samme navn, de samme parametre eller signatur og den samme returtype (eller undertype) som en metode i sin superklasse, så siges metoden i underklassen at tilsidesætte metoden i superklassen.
Metodetilsidesættelse er en af måderne, hvorpå Java opnår Run Time Polymorphism . Den version af en metode, der udføres, vil blive bestemt af det objekt, der bruges til at fremkalde den. Hvis et objekt af en overordnet klasse bruges til at kalde metoden, vil versionen i den overordnede klasse blive eksekveret, men hvis et objekt af underklassen bruges til at kalde metoden, vil versionen i den underordnede klasse blive eksekveret. Med andre ord, det er den type objekt, der henvises til (ikke typen af referencevariablen), der bestemmer, hvilken version af en tilsidesat metode, der skal udføres.
Eksempel på metodetilsidesættelse i Java
Nedenfor er implementeringen af Java Method Overriding:
Java
// Java program to demonstrate> // method overriding in java> // Base Class> class> Parent {> >void> show() { System.out.println(>'Parent's show()'>); }> }> // Inherited class> class> Child>extends> Parent {> >// This method overrides show() of Parent> >@Override> void> show()> >{> >System.out.println(>'Child's show()'>);> >}> }> // Driver class> class> Main {> >public> static> void> main(String[] args)> >{> >// If a Parent type reference refers> >// to a Parent object, then Parent's> >// show is called> >Parent obj1 =>new> Parent();> >obj1.show();> >// If a Parent type reference refers> >// to a Child object Child's show()> >// is called. This is called RUN TIME> >// POLYMORPHISM.> >Parent obj2 =>new> Child();> >obj2.show();> >}> }> |
>
>Produktion
Parent's show() Child's show()>
Regler for Java-metodetilsidesættelse
1. Tilsidesættelse og adgangsmodifikatorer
Det adgangsmodifikator for en tilsidesættende metode kan tillade mere, men ikke mindre, adgang end den tilsidesatte metode. For eksempel kan en beskyttet instansmetode i superklassen gøres offentlig, men ikke privat, i underklassen. Hvis du gør det, genereres der en kompileringsfejl.
Java
// A Simple Java program to demonstrate> // Overriding and Access-Modifiers> class> Parent {> >// private methods are not overridden> >private> void> m1()> >{> >System.out.println(>'From parent m1()'>);> >}> >protected> void> m2()> >{> >System.out.println(>'From parent m2()'>);> >}> }> class> Child>extends> Parent {> >// new m1() method> >// unique to Child class> >private> void> m1()> >{> >System.out.println(>'From child m1()'>);> >}> >// overriding method> >// with more accessibility> >@Override> public> void> m2()> >{> >System.out.println(>'From child m2()'>);> >}> }> // Driver class> class> Main {> >public> static> void> main(String[] args)> >{> >Parent obj1 =>new> Parent();> >obj1.m2();> >Parent obj2 =>new> Child();> >obj2.m2();> >}> }> |
>
>Produktion
From parent m2() From child m2()>
2. Endelige metoder kan ikke tilsidesættes
Hvis vi ikke ønsker, at en metode skal tilsidesættes, erklærer vi den som endelig . Se venligst Brug af Final med arv .
Java
// A Java program to demonstrate that> // final methods cannot be overridden> class> Parent {> >// Can't be overridden> >final> void> show() {}> }> class> Child>extends> Parent {> >// This would produce error> >void> show() {}> }> |
>
>
Produktion
13: error: show() in Child cannot override show() in Parent void show() { } ^ overridden method is final> 3. Statiske metoder kan ikke tilsidesættes (Tilsidesættelse af metode vs metodeskjul):
Når du definerer en statisk metode med samme signatur som en statisk metode i basisklassen, er den kendt som metode skjuler . Følgende tabel opsummerer, hvad der sker, når du definerer en metode med samme signatur som en metode i en superklasse.
| Superklasse-instansmetode | Superklasse statisk metode | |
|---|---|---|
| Underklasse-instansmetode | Tilsidesætter | Genererer en kompileringsfejl |
| Underklasse statisk metode | Genererer en kompileringsfejl | Skjuler |
Java
// Java program to show that> // if the static method is redefined by> // a derived class, then it is not> // overriding, it is hiding> class> Parent {> >// Static method in base class> >// which will be hidden in subclass> >static> void> m1()> >{> >System.out.println(>'From parent '> >+>'static m1()'>);> >}> >// Non-static method which will> >// be overridden in derived class> >void> m2()> >{> >System.out.println(> >'From parent '> >+>'non - static(instance) m2() '>);> >}> }> class> Child>extends> Parent {> >// This method hides m1() in Parent> >static> void> m1()> >{> >System.out.println(>'From child static m1()'>);> >}> >// This method overrides m2() in Parent> >@Override> public> void> m2()> >{> >System.out.println(> >'From child '> >+>'non - static(instance) m2() '>);> >}> }> // Driver class> class> Main {> >public> static> void> main(String[] args)> >{> >Parent obj1 =>new> Child();> >// As per overriding rules this> >// should call to class Child static> >// overridden method. Since static> >// method can not be overridden, it> >// calls Parent's m1()> >obj1.m1();> >// Here overriding works> >// and Child's m2() is called> >obj1.m2();> >}> }> |
>
>Produktion
From parent static m1() From child non - static(instance) m2()>
4. Private metoder kan ikke tilsidesættes
Private metoder kan ikke tilsidesættes, da de er bundet under kompileringstiden. Derfor kan vi ikke engang tilsidesætte private metoder i en underklasse.(Se det her for detaljer).
Java
class> SuperClass {> >private> void> privateMethod()> >{> >System.out.println(> >'This is a private method in SuperClass'>);> >}> >public> void> publicMethod()> >{> >System.out.println(> >'This is a public method in SuperClass'>);> >privateMethod();> >}> }> class> SubClass>extends> SuperClass {> >// This is a new method with the same name as the> >// private method in SuperClass> >private> void> privateMethod()> >{> >System.out.println(> >'This is a private method in SubClass'>);> >}> >// This method overrides the public method in SuperClass> >public> void> publicMethod()> >{> >System.out.println(> >'This is a public method in SubClass'>);> >privateMethod();>// calls the private method in> >// SubClass, not SuperClass> >}> }> public> class> Test {> >public> static> void> main(String[] args)> >{> >SuperClass obj1 =>new> SuperClass();> >obj1.publicMethod();>// calls the public method in> >// SuperClass> >SubClass obj2 =>new> SubClass();> >obj2.publicMethod();>// calls the overridden public> >// method in SubClass> >}> }> |
>
>Produktion
This is a public method in SuperClass This is a private method in SuperClass This is a public method in SubClass This is a private method in SubClass>
5. Den tilsidesættende metode skal have samme returtype (eller undertype)
Fra Java 5.0 og frem er det muligt at have forskellige returtyper for en overordnet metode i underklassen, men barnets returtype bør være en undertype af forælderens returtype. Dette fænomen er kendt som kovariant returtype .
Java
class> SuperClass {> >public> Object method()> >{> >System.out.println(> >'This is the method in SuperClass'>);> >return> new> Object();> >}> }> class> SubClass>extends> SuperClass {> >public> String method()> >{> >System.out.println(> >'This is the method in SubClass'>);> >return> 'Hello, World!'>;> >}> }> public> class> Test {> >public> static> void> main(String[] args)> >{> >SuperClass obj1 =>new> SuperClass();> >obj1.method();> >SubClass obj2 =>new> SubClass();> >obj2.method();> >}> }> |
>
>Produktion
This is the method in SuperClass This is the method in SubClass>
6. Påberåber tilsidesættelse af metode fra underklasse
Vi kan kalde den overordnede klassemetode i den overordnede metode ved hjælp af super nøgleord .
Java
// A Java program to demonstrate that overridden> // method can be called from sub-class> // Base Class> class> Parent {> >void> show() { System.out.println(>'Parent's show()'>); }> }> // Inherited class> class> Child>extends> Parent {> >// This method overrides show() of Parent> >@Override> void> show()> >{> >super>.show();> >System.out.println(>'Child's show()'>);> >}> }> // Driver class> class> Main {> >public> static> void> main(String[] args)> >{> >Parent obj =>new> Child();> >obj.show();> >}> }> |
>
>Produktion
Parent's show() Child's show()>
Overordnet og Konstruktør
Vi kan ikke tilsidesætte konstruktøren, da den overordnede og underordnede klasse aldrig kan have en konstruktør med samme navn (konstruktørens navn skal altid være det samme som klassenavnet).
Tilsidesættelse og undtagelseshåndtering
Nedenfor er to regler, du skal være opmærksom på, når du tilsidesætter metoder relateret til undtagelseshåndtering.
Regel #1
Hvis den overordnede superklassemetode ikke kaster en undtagelse, kan den overordnede metode kun kaste umarkeret undtagelse , vil smid en markeret undtagelse føre til en kompileringsfejl.
Java
hvis ellers java
// Java program to demonstrate overriding when> // superclass method does not declare an exception> class> Parent {> >void> m1() { System.out.println(>'From parent m1()'>); }> >void> m2() { System.out.println(>'From parent m2()'>); }> }> class> Child>extends> Parent {> >@Override> >// no issue while throwing unchecked exception> >void> m1()>throws> ArithmeticException> >{> >System.out.println(>'From child m1()'>);> >}> >@Override> >// compile-time error> >// issue while throwing checked exception> >void> m2()>throws> Exception> >{> >System.out.println(>'From child m2'>);> >}> }> |
>
>
Produktion
error: m2() in Child cannot override m2() in Parent void m2() throws Exception{ System.out.println('From child m2');} ^ overridden method does not throw Exception> Regel #2
Hvis den overordnede superklasse-metode kaster en undtagelse, kan den underklassetilsidesættende metode kun kaste den samme underklasseundtagelse. Kaste forældre undtagelser i Undtagelseshierarki vil føre til kompileringstidsfejl. Der er heller ikke noget problem, hvis den overstyrede underklassemetode ikke giver nogen undtagelse.
Java
// Java program to demonstrate overriding when> // superclass method does declare an exception> class> Parent {> >void> m1()>throws> RuntimeException> >{> >System.out.println(>'From parent m1()'>);> >}> }> class> Child1>extends> Parent {> >@Override> >// no issue while throwing same exception> >void> m1()>throws> RuntimeException> >{> >System.out.println(>'From child1 m1()'>);> >}> }> class> Child2>extends> Parent {> >@Override> >// no issue while throwing subclass exception> >void> m1()>throws> ArithmeticException> >{> >System.out.println(>'From child2 m1()'>);> >}> }> class> Child3>extends> Parent {> >@Override> >// no issue while not throwing any exception> >void> m1()> >{> >System.out.println(>'From child3 m1()'>);> >}> }> class> Child4>extends> Parent {> >@Override> >// compile-time error> >// issue while throwing parent exception> >void> m1()>throws> Exception> >{> >System.out.println(>'From child4 m1()'>);> >}> }> |
>
>
Produktion
error: m1() in Child4 cannot override m1() in Parent void m1() throws Exception ^ overridden method does not throw Exception>
Overordnet og abstrakt metode
Abstrakte metoder i en grænseflade eller abstrakt klasse er beregnet til at blive tilsidesat i afledte konkrete klasser, ellers vil en kompileringsfejl blive kastet.
Tilsidesættende og synkroniseret/strictfp-metode
Tilstedeværelsen af en synkroniseret/strictfp-modifikator med metoden har ingen effekt på reglerne for tilsidesættelse, dvs. det er muligt, at en synkroniseret/strictfp-metode kan tilsidesætte en ikke-synkroniseret/strictfp-metode og omvendt.
Bemærk:
- I C++ har vi brug for virtuelt nøgleord at opnå tilsidesættelse eller Run Time Polymorphism . I Java er metoder som standard virtuelle.
- Vi kan have metodeoverstyring på flere niveauer.
Java
// A Java program to demonstrate> // multi-level overriding> // Base Class> class> Parent {> >void> show() { System.out.println(>'Parent's show()'>); }> }> // Inherited class> class> Child>extends> Parent {> >// This method overrides show() of Parent> >void> show() { System.out.println(>'Child's show()'>); }> }> // Inherited class> class> GrandChild>extends> Child {> >// This method overrides show() of Parent> >void> show()> >{> >System.out.println(>'GrandChild's show()'>);> >}> }> // Driver class> class> Main {> >public> static> void> main(String[] args)> >{> >Parent obj1 =>new> GrandChild();> >obj1.show();> >}> }> |
>
>Produktion
GrandChild's show()>
Metodetilsidesættelse vs metodeoverbelastning
1. Overbelastning handler om den samme metode med forskellige signaturer. Tilsidesættelse handler om den samme metode og samme signatur, men forskellige klasser forbundet gennem arv.
2. Overbelastning er et eksempel på kompilertidspolymorfi og tilsidesættelse er et eksempel på runtime polymorfi .
Ofte stillede spørgsmål om Java-metodetilsidesættelse
Q1. Hvad er metodetilsidesættelse?
Som tidligere nævnt tillader overstyrede metoder Java at understøtte run-time polymorfi . Polymorfi er essentiel for objektorienteret programmering af én grund: den tillader en generel klasse at specificere metoder, der vil være fælles for alle dens derivater, mens den tillader underklasser at definere den specifikke implementering af nogle eller alle disse metoder. Tilsidesatte metoder er en anden måde, hvorpå Java implementerer den ene grænseflade, flere metoders aspekt af polymorfi. Dynamisk metodeafsendelse er en af de mest kraftfulde mekanismer, som objektorienteret design bringer med på kodegenbrug og robusthed. Evnen til at eksistere kodebiblioteker til at kalde metoder på forekomster af nye klasser uden at rekompilere og samtidig opretholde en ren abstrakt grænseflade er et dybt kraftfuldt værktøj. Tilsidesatte metoder giver os mulighed for at kalde metoder for enhver af de afledte klasser uden overhovedet at kende typen af afledt klasseobjekt.
Q2. Hvornår skal man anvende metodetilsidesættelse? (med eksempel)
Tilsidesættende og Arv : En del af nøglen til succesfuld anvendelse af polymorfi er forståelsen af, at superklasserne og underklasserne danner et hierarki, der bevæger sig fra mindre til større specialisering. Brugt korrekt giver superklassen alle elementer, som en underklasse kan bruge direkte. Den definerer også de metoder, som den afledte klasse skal implementere på egen hånd. Dette giver underklassen fleksibilitet til at definere dens metoder, men håndhæver stadig en ensartet grænseflade. Ved at kombinere arv med tilsidesatte metoder kan en superklasse således definere den generelle form for de metoder, der vil blive brugt af alle dens underklasser. Lad os se på et mere praktisk eksempel, der bruger metodetilsidesættelse. Overvej en medarbejderstyringssoftware til en organisation, lad koden have en simpel basisklasse Employee, og klassen har metoder som raiseSalary(), transfer(), promote(), .. osv. Forskellige typer medarbejdere som Manager, Engineer, ..etc kan have deres implementeringer af metoderne til stede i basisklassen Employee. I vores komplette software skal vi blot sende en liste over medarbejdere overalt og kalde passende metoder uden overhovedet at kende typen af medarbejder. For eksempel kan vi nemt hæve lønnen for alle medarbejdere ved at iterere gennem listen over medarbejdere. Hver type medarbejder kan have sin logik i sin klasse, vi behøver ikke bekymre os, for hvis raiseSalary() er til stede for en specifik medarbejdertype, ville kun den metode blive kaldt.
Java
// Java program to demonstrate application>// of overriding in Java>// Base Class>class>Employee {>>public>static>int>base =>10000>;>>int>salary() {>return>base; }>}>// Inherited class>class>Manager>extends>Employee {>>// This method overrides salary() of Parent>>int>salary() {>return>base +>20000>; }>}>// Inherited class>class>Clerk>extends>Employee {>>// This method overrides salary() of Parent>>int>salary() {>return>base +>10000>; }>}>// Driver class>class>Main {>>// This method can be used to print the salary of>>// any type of employee using base class reference>>static>void>printSalary(Employee e)>>{>>System.out.println(e.salary());>>}>>public>static>void>main(String[] args)>>{>>Employee obj1 =>new>Manager();>>// We could also get type of employee using>>// one more overridden method.loke getType()>>System.out.print(>'Manager's salary : '>);>>printSalary(obj1);>>Employee obj2 =>new>Clerk();>>System.out.print(>'Clerk's salary : '>);>>printSalary(obj2);>>}>}>>>ProduktionManager's salary : 30000 Clerk's salary : 20000>
Relateret artikel
- Dynamic Method Dispatch eller Runtime Polymorphism i Java
- Tilsidesættelse af equals()-metoden i Object-klassen
- Tilsidesættelse af toString()-metoden for Object-klassen
- Overbelastning i java
- Output af Java-program | Sæt 18 (Tilsidesættende)