[java] method overriding

Pagina: 1
Acties:
  • 106 views sinds 30-01-2008
  • Reageer

  • TrendKiller
  • Registratie: Januari 2001
  • Laatst online: 02-07 13:03
Stel ik heb een abstracte classe DataContainer, hierin zitten een aantal abstracte methoden en een aantal niet abstracte methoden. Wanneer ik nu een andere klasse heb die hiervan extend, dan moet ik alle abstracte methoden implementeren in deze nieuwe classe (bv ScreenADataContainer). Als ik bepaalde methoden optioneel wil maken, dan maak ik in de classe DataContainer een gewonde public of protected methode aan met niets in. Wanneer ik deze methode dan wil gebruiken, overschrijf ik deze in de classe ScreenADataContainer.

Mijn probleem is nu hetvolgende:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
public void init()
{
    ScreenADataContainer sdc = new ScreenADataContainer();
    sdc.setValue("iets");

    doSomething(sdc);
}

public void doSomething(DataContainer dataContainer)
{
    String aValue = dataContainer.getValue();
    System.out.println(aValue);
}

Wanneer ik deze code run, dan zou ik verwachten dat "iets" zou te voorschijn komen. Maar dit gebeurt niet. Na een beetje zoeken kwam ik erachter dat eigenlijk de methode getValue() van DataContainer werd opgeroepen.

Nu is mijn vraag, hoe kan ik ervoor zorgen dat de methode getValue() van ScreenADataContainer wordt opgeroepen. Let wel, deze methode is niet verplicht.

Ik hoop dat de uitleg + vraag een beetje duidelijk is.

  • whoami
  • Registratie: December 2000
  • Laatst online: 21:11
Die code die je daar post, dat zijn memberfuncties van ScreenADataContainer?

Hoe roep je die methoden aan?

https://fgheysels.github.io/


  • tomato
  • Registratie: November 1999
  • Niet online
Geef eens wat code van je abstract class en je ScreenADataContainer class, want ik begrijp niet wat je nu precies doet...

Verwijderd

heb je wel je methodes gemaakt? Van een (kale) abstracte kip valt niets te plukken zogenaamd.

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Weet je zeker dat je de methode goed override? Vergelijk het eens met dit:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class Test {
  public static void main(String[] ps) {
    Extension extension = new Extension();

    printBase(extension);
    printExtension(extension);
  }

  private static void printBase(Base base) {
    System.out.println("value = " + base.getValue());
  }

  private static void printExtension(Extension extension) {
    System.out.println("value = " + extension.getValue());
  }
}

class Base {
  public int getValue() {
    return 4;
  }
}

class Extension extends Base {
  public int getValue() {
    return 6;
  }
}

Beide zal 6 printen...

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • TrendKiller
  • Registratie: Januari 2001
  • Laatst online: 02-07 13:03
DataContainer en ScreenADataContainer zien er bv als volgt uit:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public abstract class DataContainer
{
    public abstract void abstractMethod();

    public void setValue(String value)
    {
    }

    public String getValue()
    {
       return "";
    }
}

public class ScreenADataContainer extends DataContainer
{
    private String _value;
    public void abstractMethod()
    {}
    public void setValue(String value)
    {
      _value = value;
    }

    public String getValue()
    {
      return _value;
    }
}

Verwijderd

Op vrijdag 07 juni 2002 15:51 schreef Trendkiller het volgende:
Nu is mijn vraag, hoe kan ik ervoor zorgen dat de methode getValue() van ScreenADataContainer wordt opgeroepen. Let wel, deze methode is niet verplicht.
je roept toch geen super aan?

  • TrendKiller
  • Registratie: Januari 2001
  • Laatst online: 02-07 13:03
Inderdaad, heb juist mijn fout gevonden, met de andere code nog eens te bekijken, zag ik een klein schrijffoutje staan, waardoor de juiste methode niet werd opgeroepen.

Niets aan de hand meer, deze code moet normaal ook werken.

Iig bedankt!

Dit topic mag gesloten worden.

  • Jelmer
  • Registratie: Maart 2000
  • Laatst online: 20:57
Op vrijdag 07 juni 2002 16:09 schreef graaff01 het volgende:

[..]

je roept toch geen super aan?
Nee, maar dat is ook niet noodzakelijk. super()/.method() zorgt er alleen voor dat je de overridden methode kan aanroepen omdat deze anders in de vergetelheid zal verdwijnen.
In c++ heb je hier ook een keyword voor nl virtual. Dit zorgt er kort gezegd voor dat methoden in een subclass worden aangeroepen als er een referentie naar de superclass is.

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Jelmer Barhorst: In c++ heb je hier ook een keyword voor nl virtual. Dit zorgt er kort gezegd voor dat methoden in een subclass worden aangeroepen als er een referentie naar de superclass is.
Om onze geachte bezoekers nog verder te informeren ;) :

In Java zijn methode standaard 'virtual' en kunnen dus normaal gesproken altijd overridden worden in een subklasse. Je kan dit echter ook voorkomen door er 'final' bij te zetten. Het is dan niet toegestaan om een methode te herdefinieren in een subklasse.

In C# is het (helaas) precies andersom: methoden zijn hier weer standaard final (eigenlijk een beetje niet) en er dus een keyword virtual waarmee je een methode 'overridable' maakt. Het is eigenlijk een goede gewoonte om alles maar virtual te maken omdat je jezelf en anderen zo niet onnodige beperkingen oplegt.

Ik zei net dat methoden 'eigenlijk een beetje niet' standaard final zijn in C#. Dat komt omdat je nog wel steeds een methode mag definieren in een subklasse met hetzelfde signature als deze 'final' methode. Dit is echter een andere methode en deze methode override dus niet de methode in de superklasse die final was.

Het mooie van C# is wel weer dat er een apart override keyword is. Als je een methode override moet je dit namelijk ook aangeven. Dit is handig omdat je zo kan controleren of er wel echt een methode override wordt (je zou een foutje kunnen maken in de naam of de parameters).

Als je dit override keyword echter vergeet, override je de virutal methode in de superklasse dus niet en introduceer je dus in feite een nieuwe methode...

Het effect daarvan zie je hier:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
using System;

class  Apple {

  virtual public bool isTasty() {
    return true;
  }

  public static void Main(string[] args) {
    GoldenDelicious golden = new GoldenDelicious();

    Console.WriteLine("Tasty? " + golden.isTasty());

    Apple apple = golden;

    Console.WriteLine("Tasty? " + apple.isTasty());
  }

}

class GoldenDelicious: Apple{

  public bool isTasty() {
    return false;
  }
}

Als je dit compileert en uitvoert krijg je dit:
code:
1
2
3
> mono Apple.exe
Tasty? False
Tasty? True

Je zit het verschil: een invocate op een GoldenDelicious zorgt ervoor dat de 'nieuwe' methode wordt uitgevoerd, een invocatie op een Apple zorgt ervoor dat de oude wordt uitgevoerd.

Wat ik niet vertelt heb, is dat de compiler wel netjes waarschuwd :) :
> mcs Apple.cs
./Apple.cs(23) warning CS114: `GoldenDelicious.isTasty' hides inherited member `Apple.isTasty'. To make the current member override that implementation, add the override keyword, otherwise use the new keyword
Je ziet dat er dus een nettere oplossing is als je echt een nieuwe methode wilt introduceren: new ervoor zetten. Dit wordt echter wel erg verwarrend en ik zou het dus ook niet gebruiken (en dus altijd overriden).

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Overigens is de Hotspot JustInTime compiler in de JVM tegenwoordig erg goed in het elimineren van de duurdere virtual dispatch, die nodig is bij het gebruik van virtuele methoden. Dit is in Java erg belangrijk omdat methoden daar immers standaard virtual zijn. Door te bekijken welke klassen er bekend zijn, kan de hotspot compiler deze virtuele methode aanroepen echter omzetten naar directe methode aanroepen.

De jitter gaat zelfs nog zover dat deze optimalisatie ongedaan kan worden gemaakt als er nieuwe klassen bekend worden die de eerdere aanname dat een methode nergens overriden wordt onjuist maken.

Alles bij elkaar doet Hotspot dit zo intelligent dat het zelfs afgeraden wordt om methoden vanwege performance redenen final te maken (vanwege design redenen is dit natuurlijk prima). Dit was vroeger nog weleens een tip om de performance van applicaties te verbeteren...

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment

Pagina: 1