Autor Beitrag
Christian R.
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Sa 04.04.09 13:20 
ausblenden volle Höhe C#-Quelltext
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:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
using System;
namespace ConsoleApplication1
{
    class ClassA
    {
        public virtual void Show()
        {
            Console.Write('A');
        }
    }

    class ClassB : ClassA
    {
        public override void Show()
        {
            Console.Write('B');
        }
    }

    class ClassC : ClassB
    {
        public virtual new void Show()
        {
            Console.Write('C');
        }
    }

    class ClassD : ClassC
    {
        public override void Show()
        {
            Console.Write('D');
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            ClassA A = new ClassA();
            A.Show();
            ClassA B = new ClassB();
            B.Show();
            ClassA C = new ClassC();
            C.Show();
            ClassA D = new ClassD();
            D.Show();
            Console.ReadLine();
        }
    }
}

// Output: ABBB


Also "override" ist mir klar. Von Ableitung zu Ableitung bleiben die Member polymorph, so wie in der Basisklasse.

"new" ist mir in soweit erst einmal klar: Ich lehne in der Ableitung das Angebot der Polymorphie ab. Es wird also der Member, der in der Ableitungshierarchie letzten Ableitung, aufgerufen, welcher noch als virtuell deklariert ist, bzw. u. U. der Member der Basisklasse, welche den Member zuerst und als nicht virtuell deklariert hat.

Aber ich kann mit "virtual new" nichts anfangen. Mein Code oben hat mir da (Edit) keinen Aufschluss geben können. Ich denke, der Compiler würde sich schon beschweren, wenn diese Deklaration nicht erlaubt, bzw. unsinnig wäre. Also muss ja was dran sein, an dieser Deklaration.

Klärt mich doch bitte mal auf.
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Sa 04.04.09 16:57 
Es gibt kein "virtual new". Das ist nicht mehr als die Kombination der zwei Keywords, der Compiler sollte da keine Fallunterscheidung eingebaut haben.
Dazu muss man natürlich erst einmal sagen: "new" macht sowieso überhaupt nichts. Damit zeigst du nur, dass du willentlich einen neuen Slot einführen willst, und unterdrückst damit die entsprechende Warnung.
So, nun zu den Slots: Das ist der Mechanismus, der hinter der ganzen Polymorphie steckt.
Jede Methode ohne override führt einen neuen Slot ein, also z.B. ClassA.Show. ClassB führt nun keinen eigenen Slot ein, sondern schreibt seine Show-Methode einfach in den bestehenden ClassA.Show-Slot. Deswegen kann mal die eine, mal die andere Methode aufgerufen werden, wenn du von einer ClassA-Variablen Show aufrufst.
ClassC führt nun also einen zweiten Slot ein - mit virtual hat das erstmal nichts zu tun. ClassD schreibt sich nun wieder dort hinein - was natürlich nur möglich ist, weil ClassC.Show eben doch virtual ist.

Die Slots der einzelnen Klassen (die von System.Object lass ich mal weg ;) ) sehen also in deinem Beispiel so aus:
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
ClassA:
0. ClassA.Show

ClassB:
0. ClassB.Show

ClassC:
0. ClassB.Show
1. ClassC.Show

ClassD:
0. ClassB.Show
1. ClassD.Show

Damit wird der Output deines Programms hoffentlich klar: Da du 4 ClassA-Variablen hast und ClassA.Show den Slot #0 eingeführt hat, wird dieser viermal aufgerufen: ABBB.
Den zweiten Slot kannst du so nutzen:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
ClassA A = new ClassA();
      A.Show();
      ClassA B = new ClassB();
      B.Show();
      ClassC C = new ClassC();
      C.Show();
      ClassC D = new ClassD();
      D.Show();
      Console.ReadLine();

Was kommt dann raus ;) ?

_________________
>λ=
Moosbüffel
Hält's aus hier
Beiträge: 2



BeitragVerfasst: Mi 20.05.09 11:24 
Das Prinzip der Slots kenne ich nicht, aber so ungefähr ist mir der Sinn wohl klar geworden. Aber wie ist das bei verwendung von Interfaces. Also wenn ClassA ein Interface Ifc verwenden würde und dann in Main nur Variablen vom Typ Ifc verwendet werden. Was passiert dann?

Vielleicht kannst Du zu den Slots auch noch kurz was schreiben. Finde dazu nichts. Scheint mir aber eine gute Erklärung der Vererbungsabhängigkeiten zu sein!?

Danke
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Mi 20.05.09 14:13 
Bei Interfaces ist es noch etwas komplizierter:
Beim Virtual Dispatch wie oben sind die Slotnummern konstant: Wenn ich ClassA.Show aufrufen will, weiß ich, dass sie in jeder abgeleiteten Klasse in Slot #0 sitzt und kann sie sofort aufrufen.
Bei Interfaces ist das nicht der Fall: Zwei Klassen, die ein Interface implementieren, müssen dessen Methoden nicht in den gleichen Slots implementiert haben. Deswegen wird ein Zwischenschritt benötigt: Der Typ des aufrufenden Objekts muss ermittelt werden, um daraus den aufzurufenden Slot auszulesen. Deswegen sind Aufrufe von Interface-Methoden auch teurer als die von virtuellen Methoden.

Hier steht wohl einiges zum Thema, aber sieht nicht nach leichter Kost aus ;) .

_________________
>λ=