Laden...

Casting von Klassenobjekten???

Erstellt von CompilerSaysNo vor 3 Jahren Letzter Beitrag vor 3 Jahren 968 Views
C
CompilerSaysNo Themenstarter:in
7 Beiträge seit 2020
vor 3 Jahren
Casting von Klassenobjekten???

Hallo liebe Community,

ich schlage mich nun bereits seit einiger Zeit mit einer Frage zum Thema "Casten von Klassenobjekten" rum und komm nicht dahinter. Ich hoffe ihr könnt mich erhellen. 😃

Ich habe zwei einfache Beispielklassen:


        class A
        {
            public int Zähler { get; protected set; }

            public virtual void ErhöheZähler()
            {
                Zähler++;
            }
        }

        class B : A
        {
            public override void ErhöheZähler()
            {
                Zähler += 5;
            }

            public void Essen()
            {
                
            }
        }

Nun zu meinem Gehirnknoten:


            A objekt1 = new A();
            A objekt2 = new B();
            **B objekt3 = objekt2;**

            objekt1.ErhöeZähler();
            objekt2.ErhöheZähler();

Den implizierten Cast in Zeile 3 will der Compiler nicht machen. Die Erklärungen, die ich bisher dazu gefunden haben lauten alle mehr oder weniger:

"Der Compiler kann hier nicht entscheiden vom welchem Typ das Objekt hinter "objekt2" ist, da es mehrere Klassen geben kann, die von A ableiten könnten und kann somit den implizierten Cast nicht durchführen."

Ok klingt soweit logisch, auch wenn es hier nur eine Subklasse gibt, aber es könnte ja noch weitere geben. Und das kann der Compiler nicht erkennen???

In Zeile 6 rufe ich nun allerdings über die API von "A" die Methode "ErhöheZähler()" auf und der Compiler erkennt direkt, dass dahinter ein Objekt des Typs B liegt und "leitet" direkt zur override-Methode von Class B um.

Warum erkennt der Compiler dann nicht auch in Zeile 3, dass hier ein Objekt von Typ B hinterliegt???

In Zeile 6 scheint der Compiler zu erkennen, dass dort ein Objekt vom Typ B hinterliegt und in Zeile 3 wieder nicht??

Ich finde auch keine Erklärungen, die dies aufklären, sondern alles was ich an Erklärungen finde geht immer so in die Richtung wie oben gennannt.

Das lässt mir einfach keine Ruhe und bremst mich in meinem weiteren Fortschritt. Denn ich bin so, dass ich immer verstehen MUSS "Warum" etwas so ist und nicht nur das es so ist. So bin ich halt und dann macht mich sowas wahnsinnig.

Ich hoffe ihr könnt mich erleuchten.

Gruß
Maik

F
10.010 Beiträge seit 2004
vor 3 Jahren

Es ist simple zu erklären.

Wenn du eine Variable A erzeugst ( A object2 ) dann steht eben A für alles was A kann und nicht für alle klassen die von A ableiten.

Da Du ErhöheZähler virtual declariert hast, wird schon die richtige funktion ausgeführt.

T
2.222 Beiträge seit 2008
vor 3 Jahren

Die Konvertierung in Zeile 3 kannst du eigentlich nur durch hartes Boxing forcieren.
Sollte man i.d.R. eigentlich vermeiden und ist auch nur nötig wenn der tatsächliche Typ explizit gefordert wäre.
Die Runtime merkt sich, dass objekt2 eigentlich von Typ B ist und ruft dann auch entsprechend die Methode von Typ B auf.
An der Stelle muss man aber dem Compiler, der dies nicht direkt erkennt, dies eben durch explizite Typenumwandlung (Boxing) mitteilen.


A objekt1 = new A();
A objekt2 = new B();
B objekt3 = (B)objekt2;

In Zeile 6 erkennt nicht der Compiler, dass es ein Objekt B ist sondern die Runtime von .NET merkt dies.
Hier wird erst zur Laufzeit sich der Typ gemerkt und die richtige Methode von Typ B aufgerufen.
Hier must du zwischen Compiler und Laufzeit immer unterscheiden.
Der Compiler sieht nur den Syntax und will daraus die Anwendung kompilieren.
Die Laufzeit hingegen muss solche Typen Informationen aber kennen und merken.

Ist als Einsteiger noch recht schwierig es zu verstehen, lernt man aber mit der Zeit.
Im besten Fall sollte man von einer expliziten Konvertierung auch nur in den nötigsten Fällen gebrauch machen müssen.
Es ist immer besser, wenn du wie bei Zeile 2 dann gegen die Basis Programmierst.
Im Bestfall handelt es sich dann um ein Interface, dass deine Klasse implementiert.
Dadurch ist dein Code auch austauschbar bzw. kannst du mit unterschiedlichen Implementierungen gegen deinen Code arbeiten.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

W
955 Beiträge seit 2010
vor 3 Jahren

Die Konvertierung in Zeile 3 kannst du eigentlich nur durch hartes Boxing forcieren.

C
CompilerSaysNo Themenstarter:in
7 Beiträge seit 2020
vor 3 Jahren

Hier must du zwischen Compiler und Laufzeit immer unterscheiden.

Ich denke dies ist der entscheidende Hinweis. Dann muss ich mich dringend nochmal genauer mit diesen beiden Elementen befassen. Wenn du dazu gute Quellen hast, dann würde ich mich freuen, ansonsten finde ich da sicher auch selbst etwas.

Es kann so einfach sein, aber wenn einem das entscheidende Puzzlestück fehlt, dann hängt man erbarmungslos fest.^^

Vielen Dank.

Gruß
Maik

C
CompilerSaysNo Themenstarter:in
7 Beiträge seit 2020
vor 3 Jahren

Boxing ist der Prozess der Konvertierung eines Wertetypes in object damit der Wert in der Heap gespeichert werden kann. .

Ich habe vermutet, dass damit ein expliziter Cast gemeint ist. Sollte dies nicht so sein, dann bin ich über das Thema Boxing wohl noch nicht gestolpert...

T
2.222 Beiträge seit 2008
vor 3 Jahren

@witte
Hast recht, explizite Konvertierung ist hier der richtige Begriff.
Mein Fehler!

@CompilerSaysNo
Du musst, wie in dem Code Beispiel, den Typen hier explizit konvertieren.
Boxing war hier der falsche Begriff von meiner Seite aus.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

W
955 Beiträge seit 2010
vor 3 Jahren

@CompilerSaysNo: Wenn Du viel Zeit hast kannst du dir mal das OO-Buch anschauen welches hier unter Ressourcen verlinkt ist. Der Link zeigt auf eine lesbare Online-Version. Da wird das m.E. sehr gut erklärt - z.B. unter dynamischer Polymorphie. Musst mal schauen ob dir das liegt.