I Java är Overriding en funktion som tillåter en underklass eller underklass att tillhandahålla en specifik implementering av en metod som redan tillhandahålls av en av dess superklasser eller överordnade klasser. När en metod i en underklass har samma namn, samma parametrar eller signatur och samma returtyp (eller undertyp) som en metod i sin superklass, så sägs metoden i underklassen att åsidosätta metoden i superklassen.
Metodöverstyrning är ett av sätten som Java uppnår Run Time Polymorphism . Den version av en metod som exekveras kommer att bestämmas av objektet som används för att anropa den. Om ett objekt av en överordnad klass används för att anropa metoden, kommer versionen i den överordnade klassen att exekveras, men om ett objekt av underklassen används för att anropa metoden, kommer versionen i den underordnade klassen att exekveras. Med andra ord, det är den typ av objekt som avses (inte typen av referensvariabel) som bestämmer vilken version av en åsidosatt metod som kommer att exekveras.
Exempel på metodöverstyrning i Java
Nedan är implementeringen av 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();> >}> }> |
alfabetiska siffror
>
>Produktion
Parent's show() Child's show()>
Regler för överstyrning av Java-metoder
1. Åsidosättande och åtkomstmodifierare
De åtkomstmodifierare för en åsidosättande metod kan tillåta mer, men inte mindre, åtkomst än den åsidosatta metoden. Till exempel kan en skyddad instansmetod i superklassen göras offentlig, men inte privat, i underklassen. Om du gör det genereras ett kompileringsfel.
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. Slutliga metoder kan inte åsidosättas
Om vi inte vill att en metod ska åsidosättas, deklarerar vi den som slutlig . Snälla se Använder 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. Statiska metoder kan inte åsidosättas (Åsidosättande av metod vs metod att dölja):
När du definierar en statisk metod med samma signatur som en statisk metod i basklassen kallas den metod att dölja . Följande tabell sammanfattar vad som händer när du definierar en metod med samma signatur som en metod i en superklass.
| Superclass Instance Method | Superklass statisk metod | |
|---|---|---|
| Subclass Instance Method | Åsidosätter | Genererar ett kompileringsfel |
| Underklass Statisk metod | Genererar ett kompileringsfel | Döljer sig |
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. Privata metoder kan inte åsidosättas
Privata metoder kan inte åsidosättas eftersom de är bundna under kompileringstiden. Därför kan vi inte ens åsidosätta privata metoder i en underklass.(Se detta för 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
alfa-beta beskärning
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 överordnade metoden måste ha samma returtyp (eller undertyp)
Från Java 5.0 och framåt är det möjligt att ha olika returtyper för en överordnad metod i den underordnade klassen, men barnets returtyp bör vara en undertyp av förälderns returtyp. Detta fenomen är känt som kovariant returtyp .
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. Åberopar åsidosatt metod från underklass
Vi kan anropa den överordnade klassmetoden i den överordnade metoden med hjälp av super nyckelord .
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()>
Överordnade och Konstruktör
Vi kan inte åsidosätta konstruktorn eftersom den överordnade och underordnade klassen aldrig kan ha en konstruktor med samma namn (konstruktorns namn måste alltid vara detsamma som klassnamnet).
Åsidosättande och undantagshantering
Nedan finns två regler att notera när man åsidosätter metoder relaterade till undantagshantering.
Regel #1
Om den överordnade superklassens metoden inte ger ett undantag, kan den åsidosatta metoden för underklassen bara kasta okontrollerat undantag , kommer att kasta ett markerat undantag att leda till ett kompileringsfel.
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
Om den åsidosatta metoden för superklass verkligen ger ett undantag, kan den åsidosatta metoden för underklass bara kasta samma underklassundantag. Kasta förälder undantag i Undantagshierarki kommer att leda till kompileringstidsfel. Det är heller inga problem om den åsidosatta metoden för underklassen inte ger något undantag.
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>
Överordnad och abstrakt metod
Abstrakta metoder i ett gränssnitt eller abstrakt klass är avsedda att åsidosättas i härledda konkreta klasser, annars kommer ett kompileringsfel att kastas.
Åsidosättande och synkroniserad/strictfp-metod
Förekomsten av en synkroniserad/strictfp-modifierare med metoden har ingen effekt på reglerna för åsidosättande, det vill säga det är möjligt att en synkroniserad/strictfp-metod kan åsidosätta en icke-synkroniserad/strictfp-metod och vice versa.
Notera:
- I C++ behöver vi virtuella nyckelord för att uppnå åsidosättande eller Run Time Polymorphism . I Java är metoderna virtuella som standard.
- Vi kan ha metodöverstyrning på flera nivåer.
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();> >}> }> |
>
>
np.linspaceProduktion
GrandChild's show()>
Metodöverskridande vs metodöverbelastning
1. Överbelastning handlar om att samma metod har olika signaturer. Åsidosättande handlar om samma metod och samma signatur men olika klasser kopplade genom arv.
2. Överbelastning är ett exempel på kompilatorns polymorfism och åsidosättande är ett exempel på körtid polymorfism .
Vanliga frågor om överstyrning av Java-metoder
Q1. Vad är metodöverskridande?
Som nämnts tidigare tillåter åsidosatta metoder Java att stödja körtidspolymorfism . Polymorfism är väsentlig för objektorienterad programmering av en anledning: den tillåter en allmän klass att specificera metoder som kommer att vara gemensamma för alla dess derivator samtidigt som det tillåter underklasser att definiera den specifika implementeringen av några eller alla av dessa metoder. Åsidosatta metoder är ett annat sätt som Java implementerar ett gränssnitt, flera metoders aspekt av polymorfism. Dynamisk metodsändning är en av de mest kraftfulla mekanismerna som objektorienterad design ger utslag på kodåteranvändning och robusthet. Möjligheten att existera kodbibliotek för att anropa metoder på instanser av nya klasser utan att kompilera om samtidigt som ett rent abstrakt gränssnitt bibehålls är ett mycket kraftfullt verktyg. Åsidosatta metoder tillåter oss att anropa metoder för någon av de härledda klasserna utan att ens veta vilken typ av härlett klassobjekt.
Q2. När ska man tillämpa metodöverskrivning? (med exempel)
Åsidosättande och Arv : En del av nyckeln till att framgångsrikt tillämpa polymorfism är att förstå att superklasserna och underklasserna bildar en hierarki som går från mindre till större specialisering. Rätt använt tillhandahåller superklassen alla element som en underklass kan använda direkt. Den definierar också de metoder som den härledda klassen måste implementera på egen hand. Detta ger underklassen flexibilitet att definiera sina metoder, men upprätthåller ändå ett konsekvent gränssnitt. Således, genom att kombinera arv med åsidosatta metoder, kan en superklass definiera den allmänna formen av metoderna som kommer att användas av alla dess underklasser. Låt oss titta på ett mer praktiskt exempel som använder metodöverstyrning. Tänk på en anställdhanteringsprogramvara för en organisation, låt koden ha en enkel basklass Employee, och klassen har metoder som raiseSalary(), transfer(), promote(), .. etc. Olika typer av anställda som Manager, Engineer, ..etc kan ha sina implementeringar av metoderna som finns i basklassen Employee. I vår kompletta programvara behöver vi bara skicka en lista över anställda överallt och anropa lämpliga metoder utan att ens veta vilken typ av anställd. Till exempel kan vi enkelt höja lönen för alla anställda genom att iterera genom listan över anställda. Varje typ av anställd kan ha sin logik i sin klass, vi behöver inte oroa oss för om raiseSalary() finns för en specifik anställdstyp, skulle bara den metoden anropas.
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>
Relaterad artikel
- Dynamic Method Dispatch eller Runtime Polymorphism i Java
- Åsidosätter metoden equals() för objektklassen
- Åsidosätter metoden toString() för objektklassen
- Överbelastning i java
- Utdata från Java-program | Set 18 (Åsidosättande)