Unterschied new und override



  • Was ist der Unterschied zwischen new und override in einer Methode?
    Beide male überschreibe ich doch die Methode der Basisklasse, oder? 😕



  • Mit new verdeckst du die Methode der Basisklasse. Sie wird aber nicht dynamisch gebunden.
    Wenn du ein Objekt der abgeleiteten Klasse hast, aber mit einer Referenz der Basisklasse die Methode aufrufst, dann wird die Methode der Basisklasse aufgerufen.
    override verwendet man bei virtuellen (dynamisch gebundenen) Methoden.



  • hm, sorry wenn ich nerve aber ich steh immernoch aufm Schlauch. Was override macht is mir klar. Aber ich versteh den Sinn von "new" nicht. In C++ oder Java hab ich sowas auch noch nie gebraucht. Könntest du kurz ein kleines Beispiel posten, wo man new braucht?? 😕



  • In Java kannst du sowas gar nicht brauchen, da alle Methoden dynamisch gebunden werden (außer statische freilich).

    Betrachte folgenden C++ Code:

    class A
    {
        void myMethod();
    };
    
    class B  :  public A
    {
        void myMethod();
    };
    

    frag mich nicht, wozu man sowas braucht. Ich habe es noch nie gebraucht (fällt mir jedenfalls grad keine Situation ein). Der Punkt ist auch ein anderer. Wenn du das selbe in C# programmierst, will C#, dass du die Methode mit new redefinierst, um deutlich zu machen, dass du keine dynamische Bindung wünscht.
    Sonst kämst du vielleicht auf die Idee, dass

    class B  :  A
    {
        void myMethod();
    }
    

    Die Methode von A überschreibt und bei einem B - Objekt auch immer B.myMethod() aufgerufen wird, weil es dynamisch gebunden wird, was aber nicht der Fall ist. Mit new machst du deutlich, dass das nicht der Fall ist.

    Außerdem steckt da noch ne andere Motivation dahinter, genau die selbe wie bei override: Wenn du in Klasse B eine Methode virtual foo() hast und irgendwann willst du sie in der Basisklasse auch haben, denkst aber nicht mehr daran, dass es sie in B schon gibt, dann meckert der Compiler. Bei C++ würdest du einfach mal schnell die bereits existierende Methode in B schon dynamisch dazu binden, ohne dass du es merkst.

    Kurz: C# will, dass du den Compiler immer mitteilst, was deine Absicht ist:
    - überdecken der Methode der Basisklasse
    - redefinieren der dynamisch gebundenen Methode der Basisklasse

    Hilft, Fehler zu vermeiden. 🙂



  • Optimizer schrieb:

    In Java kannst du sowas gar nicht brauchen, da alle Methoden dynamisch gebunden werden (außer statische freilich).

    Und was ist mit final?

    frag mich nicht, wozu man sowas braucht. Ich habe es noch nie gebraucht (fällt mir jedenfalls grad keine Situation ein).

    Ich schon.

    ich habe eine Klasse List, welche eine einfach verkettete Liste darstellt. Die Methode size() zählt die Elemente und liefert die Anzahl zurück.

    Nun habe ich eine Klasse CountedList, welche sich die Anzahl der Elemente merkt.

    Dann habe ich CountedList von List erben lassen und alle Methoden neu definiert die die anzahl der Elemente beeinflussen - allerdings non virtual - weil ich in CountedList ja immer die List methode aufgerufen habe.

    Funktioniert super. Komposition ging nicht, weil CountedList List als template Parameter bekam.



  • Shade Of Mine schrieb:

    Optimizer schrieb:

    In Java kannst du sowas gar nicht brauchen, da alle Methoden dynamisch gebunden werden (außer statische freilich).

    Und was ist mit final?

    Die Methode wird trotzdem dynamisch gebunden, sie darf in weiter abgeleiteten Klassen nur nicht redefiniert werden. Die einzige Möglichkeit, eine Methode nicht dynamisch gebunden aufzurufen, ist static oder über den Klassennamen.

    frag mich nicht, wozu man sowas braucht. Ich habe es noch nie gebraucht (fällt mir jedenfalls grad keine Situation ein).

    Ich schon.

    ich habe eine Klasse List, welche eine einfach verkettete Liste darstellt. Die Methode size() zählt die Elemente und liefert die Anzahl zurück.

    Nun habe ich eine Klasse CountedList, welche sich die Anzahl der Elemente merkt.

    Dann habe ich CountedList von List erben lassen und alle Methoden neu definiert die die anzahl der Elemente beeinflussen - allerdings non virtual - weil ich in CountedList ja immer die List methode aufgerufen habe.

    Funktioniert super. Komposition ging nicht, weil CountedList List als template Parameter bekam.

    Dein size() ist nicht dynamisch gebunden, oder? Das heisst, wenn du einen List-Zeiger hast, der auf eine CountedList zeigt, werden bei size() trotzdem die Elemente erst gezählt. Finde ich nicht sehr geschickt, vor allem ist mir der Vorteil jetzt immer noch nicht klar.



  • Zu dem final nochmal:

    class A
    {
        void foo()    {}
    }
    
    class B extends A
    {
        final void foo()    {}
    }
    
    class C extends B
    {
    }
    

    Wenn du jetzt mit ner A-Referenz foo() aufrufst, wird A.foo() aufgerufen, wenn du ein A-Objekt hast, amsonsten B.foo(). Aber dynamisch gebunden ist sie ja, wir haben ne A-Referenz.



  • Optimizer schrieb:

    Shade Of Mine schrieb:

    Optimizer schrieb:

    In Java kannst du sowas gar nicht brauchen, da alle Methoden dynamisch gebunden werden (außer statische freilich).

    Und was ist mit final?

    Die Methode wird trotzdem dynamisch gebunden, sie darf in weiter abgeleiteten Klassen nur nicht redefiniert werden. Die einzige Möglichkeit, eine Methode nicht dynamisch gebunden aufzurufen, ist static oder über den Klassennamen.

    Echt? Finde ich Performance Verschwendung... Weil ja schon während dem Kompilieren feststeht, welche Methode aufgerufen wird - wozu also dynamisch binden?

    Dein size() ist nicht dynamisch gebunden, oder? Das heisst, wenn du einen List-Zeiger hast, der auf eine CountedList zeigt, werden bei size() trotzdem die Elemente erst gezählt. Finde ich nicht sehr geschickt, vor allem ist mir der Vorteil jetzt immer noch nicht klar.

    Ja - ist aber irrelevant weil es ein value-type ist. Und man verwendet keine value-typen Polymorph. Geht in der STL ja sowieso nicht, weil kein virtueller Dtor vorhanden ist. Und es macht auch keinen Sinn 😉



  • Shade Of Mine schrieb:

    Optimizer schrieb:

    Shade Of Mine schrieb:

    Optimizer schrieb:

    In Java kannst du sowas gar nicht brauchen, da alle Methoden dynamisch gebunden werden (außer statische freilich).

    Und was ist mit final?

    Die Methode wird trotzdem dynamisch gebunden, sie darf in weiter abgeleiteten Klassen nur nicht redefiniert werden. Die einzige Möglichkeit, eine Methode nicht dynamisch gebunden aufzurufen, ist static oder über den Klassennamen.

    Echt? Finde ich Performance Verschwendung... Weil ja schon während dem Kompilieren feststeht, welche Methode aufgerufen wird - wozu also dynamisch binden?

    Schau bitte noch einmal mein code-Beispiel an. Stell dir jetzt eine Referenz vom Typ A vor. Es steht zur Compilierzeit nicht fest, welche Methode aufgerufen wird.
    Wenn du ein A-Objekt hast, wird A.foo() aufgerufen, bei einem B- und C-Objekt B.foo(). Das final verbietet nur das redefinieren in der Klasse C, dynamisch gebunden wird die Methode aber trotzdem.

    Ja - ist aber irrelevant weil es ein value-type ist. Und man verwendet keine value-typen Polymorph. Geht in der STL ja sowieso nicht, weil kein virtueller Dtor vorhanden ist. Und es macht auch keinen Sinn

    Gut, man "macht es halt nicht". In der STL wird halt ohne Vererbung gearbeitet. Hat seine Vorteile ebenso wie Nachteile.


Anmelden zum Antworten