Problem mit Polymorphie



  • Hallo zusammen,

    ich habe hier ein Interface und zwei Klassen, die von einander erben:

    public interface MyInterface {
    	public int g();
    }
    
    class Base implements MyInterface {
    	public int i = 1;
    	public int g() { return f(); }
    	protected int f() { return i; }
    }
    
    class Derived extends Base {
    	public int i = 2;
    	protected int f() { return -i; }
    	protected int h() { return i + i; }
    	protected int p() { return i * i; }
    }
    
    public static void main(String[] args) {
    	Base base = new Base() ;
    	Derived derived = new Derived();
    	MyInterface restricted = derived;
    	int temp = base.i; // a
            temp = base.g(); // b
    	base = derived;
    	temp = base.i; // c
    	temp = base.g() ; // d
    	temp = restricted.g(); // e
    	restricted = base;
    	temp = restricted.g(); // f
    }
    

    Jetzt ist meine Aufgabe, den Wert von temp an den Stellen a, b, c, d, e und f zu bestimmen.

    Das klappt auch ganz gut, doch einen Schritt verstehe ich nicht:

    c) temp == 1. Warum? Zuvor wurde meinem Baseobjekt eine Referenz auf ein Derivedobjekt gegeben. Das bedeutet doch, dass das Attribut nun überschrieben werde müsste und i == 2 gelten müsste. Das stimmt aber nicht. Warum?

    Könnt ihr mir helfen?

    Vielen Dank
    LG, freakC++



  • freakC++ schrieb:

    c) temp == 1. Warum? Zuvor wurde meinem Baseobjekt eine Referenz auf ein Derivedobjekt gegeben. Das bedeutet doch, dass das Attribut nun überschrieben werde müsste und i == 2 gelten müsste. Das stimmt aber nicht. Warum?

    Da wird doch nichts überschrieben. Das i in der Derived überdeckt das i aus der Basisklasse. Innerhalb der Basisklasse wird weiterhin das Base-i verwendet. Genauso, wenn du über eine Base-Referenz auf das Objekt zugreifst.

    Das was du "Überschreiben" nennst (falsche Übersetzung von "override" IMHO, liest man aber überall so), d.h. das Verwenden des Members der abgeleiteten Klasse unabhängig vom statischen Typ der Referenz, funktioniert nur bei Methoden (➡ virtual in C++).



  • Bashar schrieb:

    Innerhalb der Basisklasse wird weiterhin das Base-i verwendet.

    Aber ich verwende doch gar nicht mehr die Basisklasse, weil auf base nun eine Referenz eines derived Objekts ist.

    Danke dir! 🙂



  • freakC++ schrieb:

    Aber ich verwende doch gar nicht mehr die Basisklasse, weil auf base nun eine Referenz eines derived Objekts ist.

    Nee, der statische Typ von base ist Base.



  • Mmmhh...also ganz verstehe ich das noch nicht :). Ich habe mir mal folgendes anderes Beispiel ausgedacht:

    public class A {
    
    	private String getClassName() {
    		return "Ich bin in Klasse A";
    	}
    
    	public void printName() {
    		System.out.println(getClassName());
    	}
    }
    
    public class B extends A{
    
    	private String getClassName() {
    		return "Ich bin in Klasse B";
    	}
    }
    
    public static void main(String[] args) {
    		B b = new B();
    		b.printName();
    }
    

    Es wird nun "Ich bin in der Klasse A" ausgegeben. Aber waurm? Ich schildere euch mal meinen Gedankengang und ich würde mich über ein lautes "HAAALT" freuenl, wenn es anfängt, falsch zu werden:

    Ich rufe die von A geerbte Methode "printName()" auf. Diese benötigt die Methode getClassName(). Diese wurde direkt in B implementiert und sollte meines Verständnisses jetzt ausgeführt werden. Es wird aber die Methode von A ausgeführt.

    So, jetzt ändere ich mal die Methodensignatur von getClassName() von private in protected. Nun wird "Ich bin in Klasse B" ausgegeben. Warum? Muss die Methode erst vererbt werden, um korrekt überschrieben zu werden?

    In beiden Fällen verfügt doch B über eine Mehode "getClassName()".... 😕

    Wo liegt mein Fehler?

    Vielen Dank
    LG, freakC++



  • Private Methoden sind in den abgeleiteten Klassen nicht sichtbar und können daher auch nicht überschrieben werden.

    Wenn Du an die Methoden die Annotation @Override hängst, sagt Dir das auch der Compiler.

    Zu deinem ersten Beispiel: Felder können niemals überschrieben (im Sinne von virtual) werden.



  • Java ist nicht C++ 🙂 Du kannst in Java keine privaten Methoden überschreiben. Sowas fällt einem übrigens auch gleich auf, wenn man Override-Annotations in den Code setzt, dann meckert nämlich i.d.R. der Compiler.



  • Bashar schrieb:

    Innerhalb der Basisklasse wird weiterhin das Base-i verwendet.

    Kann es sein, dass Attribute generell statisch gebunden werden? Dann würde es für mich einen Sinn machen....



  • Ja, private Methoden können nicht überschrieben werde, aber ich spendiere ihr doch den gleichen Namen. Warum funktioniert es dennoch nicht?



  • Weil private Methoden nicht überschrieben werden können?

    Da private Methoden nicht überschrieben werden können, muss die JVM innerhalb von A.printName auch nicht schauen, ob jemand getClassName überschrieben hat und tut dies auch nicht. Sie wird - wegen dieser Tatsache - immer getClassName in A aufrufen.

    Wenn die Methode einen anderen Namen hätte, wäre es kein überschreiben.



  • LordJaxom schrieb:

    Weil private Methoden nicht überschrieben werden können?

    Da private Methoden nicht überschrieben werden können, muss die JVM innerhalb von A.printName auch nicht schauen, ob jemand getClassName überschrieben hat und tut dies auch nicht. Sie wird - wegen dieser Tatsache - immer getClassName in A aufrufen.

    Wenn die Methode einen anderen Namen hätte, wäre es kein überschreiben.

    Da ist was Wahres dran 😃 . Danke!


Anmelden zum Antworten