Methoden überschreiben ?

Status
Nicht offen für weitere Antworten.

gustav-mega

Bekanntes Mitglied
Hallo,

kann mir vielleicht jemend sagen, warum bei ((A)a).op(4); das gleiche wie bei b.op(4); ausgegeben wird???
Code:
class A
{
    int x;
    
void op(int a)
    {
        System.out.println(x+3);
    }
}

class B extends A
{
    int x;

    void op(int y)
    {
        System.out.println(x+4);
    }


    public static void main(String[] args)
    {
        B b = new B();
        A a = b;
        a.x = 9;
        ((A)a).op(4);
        b.op(4);
    }
}

Gruß,
G.M.
 
Schau dir mal Polymorphie an.
Das Objekt bleibt immer vomTyp B egal ob die es zu A castest oder in eine Variable vom Typ A speicherst.
 
Hab mal den QT etwas vereinfacht:

B.java:
Code:
class A {
    int x;
   
    void op() {
        System.out.println(x + 3);
    }
}

class B extends A {
    int x;

    void op() {
        System.out.println(x + 4);
    }

    public static void main(String[] args) {
        B b = new B();
        A a = b;
        a.x = 9;
        a.op(); //gibt 4 aus, d.h. a.x = 9 hat nichts! verändert
        b.op(); //gibt auch 4 aus, logisch, da die selbe Methode wie a.op();

        ((B)a).x = 9; //hier wird explizit zu B gecastet, obwohl es "eigentlich" schon ein B ist!
        a.op(); //und sieheda: plötzlich ist die Ausgabe 4+9=13
        b.op(); //hier auch 13
    }
}

und jetzt erklär mir bitte mal warum nur der Aufruf ((B)a).x = 9; etwas an dem x ändert! Bin jetz etwas verwirrt!
 
Wie jetzt?
Du änderst doch die Instanzvariable die kannst du auch ändern ohne zu casten(nötigen Zugriffsrecht vorrausgesetzt).

Bei all deinen Aufrufen wird aber immer die Methode op() der Klasse b ausgeführt, und darum gings doch oder nicht?
 
ja, das ursprüngliche Beispiel zielte wohl auf die Methode, das ist ja auch klar, dass die überladene Version genutzt wird. (überladen zu sagen ist doch nicht richtig, im englischen heisst es override, nicht overload, gibts da n deutsches Wort für?)

Mir ging es eher um die Variable ich ich ändere: Wenn ich sage:
Code:
a.x = 9;
a.op();
Dann denke ich, dass
Code:
System.out.println(x + 4);
aus B.op()
9+4 = 13 ausgibt.

Dies wird aber nicht erreicht. x ist weiterhin 0, es wird 4 ausgegeben.

Da durch aufrufen von a.op() die Methode B.op() aufgerufen wird, denke ich, dass durch Setzen von a.x auch das x "in B" gesezt wird.
Aber ich habe wahrscheinlich nicht B.x geändert, wie es sein sollte, sondern A.x.

Versteht mich einer oder laber ich kompletten Müll?
 
du hast da glaub ich was verwechselt...
überladen (overload): wenn du mehrere funktionen hast die gleich heissen aber unterschiedliche parameter annehmen
überschreiben (override): wenn du eine methode einer deiner super klassen überschreibst 😉
 
Liegt das von dir beobachtete Verhalten nicht eher an der überdeckten Variable in Klasse B? Beide Klassen sowohl Super als auch Subklasse definieren eine Membervariable x - sowas nennt man glaub ich shadowed-Variables? 😉 - habe das dunkel in Erinnerung mal gelernt zu haben...
Wenn du jetzt auf x zugreifst, tust du das in der superklasse - die Ausgabe von op greift auf die eigene Membervariable zu - Ergebnis für dich unbefriedigend 😉 ...
hier wäre also das Verzichten der zweiten Variablendeklaration angebracht - und ein protected sinnig - evtl. auch das Nutzen einer entsprechenden set-Methode um die geerbte Variable zu beschreiben.

aber evtl. hab ich auch nur Tomaten auf den Augen und seh auch grad nicht so das problem 😉 - vielleicht ists für mich auch schon zu spät... gut nacht allerseits! 😉
 
ziemlich richtig:

x versteckt die Membervariable von A (hiding)

und: immer wenn auf variablen, überladene (nicht überschriebene!) Methode usw. zugegriffen wird, dann wird zur CompileZeit entschieden, was man nimmt

ganz unabhängig vom RuntimeTyp

((B)a).x = 9;

ist vom Typ B, also nimmt der Compiler das B.x

und bei der Zeile

a.x = 9

wählt der Compiler schon das A.x


also:

"Hiding" ist shit, am besten komplett vermeiden
 
etwas vereinfacht
Code:
class A { int x; }
class B extends A {int x; }
public class Hiding {
    public static void main(String[] args) {
        B b = new B(); // es gibt nur eine Instanz!
        A a = b; 
        a.x = 1; 
        b.x = 2;
        System.out.println(a.x);
        System.out.println(b.x);
    }
}
 
Status
Nicht offen für weitere Antworten.

Zurück
Oben