In Java gebeurt de resolutie van overbelasting (overloading) en overschrijving (overriding) van methoden volgens bepaalde regels. Bij overbelasting kiest de compiler de meest geschikte methode uit alle versies tijdens de compilatie, op basis van het type argumenten op het moment van aanroep.
Belangrijke punten:
Voorbeeld:
class Super { void print(Number n) { System.out.println("Super Number"); } } class Sub extends Super { void print(Integer i) { System.out.println("Sub Integer"); } } ... Sub s = new Sub(); s.print(5); // Sub Integer s.print(5.0); // Super Number
Hier zal print(Integer) worden aangeroepen voor een argument van het type Integer, terwijl voor het type Double de oudermethode wordt aangeroepen.
Als in de afgeleide klasse een methode is overschreven (override) en overbelast (overload), welke wordt dan aangeroepen bij polymorfisme?
Antwoord: Bij polymorfisme wordt altijd de versie van de methode gekozen op basis van het werkelijke type van het object voor overschreven methoden (overriding). Voor overbelaste methoden is de keuze gebaseerd op het type referentie en gebeurt dit tijdens de compilatie.
class A { void test(Number n) { System.out.println("A:Number"); } } class B extends A { void test(Integer n) { System.out.println("B:Integer"); } @Override void test(Number n) { System.out.println("B:Number"); } } ... A obj = new B(); obj.test(1); // Roept B:Number aan, ondanks dat test(Integer) bestaat
Verhaal
Een ontwikkelaar voegde een overbelaste versie van een methode toe in de subklasse, in de veronderstelling dat deze zou worden aangeroepen voor alle afgeleiden. Het werd duidelijk in productie dat het aanroepen via een referentie van de bovenliggende klasse leidde tot de keuze van de methode op basis van het type referentie, en niet het object. Uiteindelijk werd de benodigde logica niet uitgevoerd.
Verhaal
In een groot project werd per ongeluk de methode equals(Object) overbelast met de handtekening equals(MyClass obj), in de veronderstelling dat deze de standaard equals zou vervangen. Bij vergelijking in HashSet-collecties werkte de standaard equals(Object), wat leidde tot inconsistentie in de logica en verlies van gegevens.
Verhaal
Bij het toevoegen van een nieuwe versie van de methode met varargs aan de hiërarchie van klassen, leek het erop dat de juiste versie voor arrays zou worden aangeroepen. Echter, bij het expliciet doorgeven van een array, koos de compiler niet de juiste overbelasting, waardoor de verwerking ongeldig was en de bug lang onopgemerkt bleef.