C # - Explizite Schnittstellen mit Vererbung?

7

Ausgabe:
B- & gt; Hallo! von Explizit.

Sollte es nicht sein:?
A- & gt; Hallo! von Explizit.

Warum wird (IHello) nicht explizit ein Call IHello.Hello () aus der Klasse A geworfen?

%Vor%     
Naximus 06.12.2009, 20:33
quelle

4 Antworten

18

Nein, sollte es nicht.

Der Aufruf von Hello entspricht dem auskommentierten - die Route zum Abrufen von IHello spielt keine Rolle (es sei denn, es ist eine Überprüfung oder Konvertierung der Ausführungszeit erforderlich); Der Typ der Kompilierzeit ist nur IHello , und das Interface-Mapping ist das gleiche, wie Sie es auch bekommen.

Wenn eine Schnittstelle mehr als einmal in der Typhierarchie explizit implementiert wird, wird die Implementierung im am meisten abgeleiteten Typ verwendet. (Wenn über die Schnittstelle aufgerufen.)

Aus Abschnitt 13.4.4 der C # 3.0-Spezifikation:

  

Interface Mapping für eine Klasse oder   struct C lokalisiert eine Implementierung für   jedes Mitglied jeder Schnittstelle   in der Basisklassenliste von C. angegeben   Die Implementierung eines bestimmten   Interface-Mitglied I.M, wo ich das ist   Schnittstelle, in der das Mitglied M ist   erklärt, wird durch Prüfung festgestellt   jede Klasse oder Struktur S, beginnend mit   C und Wiederholen für jeden sukzessive   Basisklasse von C, bis eine Übereinstimmung ist   gefunden:

     
  • Wenn S eine Deklaration enthält   eines expliziten Schnittstellenmitglieds   Implementierung, die I und M entspricht,   dann ist dieses Mitglied die Implementierung   von I.M.
  •   
  • Andernfalls, wenn S eine Deklaration eines nicht statischen öffentlichen Mitglieds enthält, das M entspricht, dann ist dieses Mitglied die IM-Implementierung. Wenn mehr als ein Mitglied übereinstimmt, ist nicht angegeben, welches Mitglied die IM-Implementierung ist auftreten, wenn S ein konstruierter Typ ist, bei dem die beiden im generischen Typ deklarierten Elemente unterschiedliche Signaturen haben, aber die Typargumente ihre Signaturen identisch machen.
  •   
    
Jon Skeet 06.12.2009, 20:38
quelle
3

(A) a tut nichts. Der Verweis ist bereits als ein deklariert, so dass es zu A wird keine Wirkung haben.

Obwohl Ihr Verweis als A deklariert ist, ist das Objekt, auf das er verweist, vom Typ B. Wenn Sie dieses Objekt in IHallo umwandeln, ruft ein Aufruf von Hello () die explizite Implementierung von Hello von Objekt B auf.

Die Ausgabe ist genau wie erwartet.

    
Adam Ralph 06.12.2009 20:41
quelle
0

Nein, wenn Sie eine neue -Methode (ToString) erstellen, ist diese nicht virtuell. Neu bedeutet nur, dass es Ihnen nichts ausmacht, die Version in der Basisklasse zu "verstecken" - wenn Sie sie also mit einem Verweis aufrufen, den Sie auf einen bestimmten Typ (A) umgewandelt haben, führt sie die Methode in Klasse A aus, unabhängig davon der tatsächliche Typ des Objekts, das Sie anrufen. (Sie haben A.ToString () aufgerufen, damit A.ToString ())

ausgeführt wurde

Wenn Sie eine virtuelle -Methode erstellen, wird unabhängig vom Typ, auf den Sie die Referenz referenzieren, die Implementierung vom tatsächlichen Typ des Objekts verwendet (dh Sie haben ein B erstellt, also beim Aufruf (was auch immer das Objekt ist). Hallo, es nannte B. Hallo)

Der entscheidende Unterschied ist, dass ein Anruf virtuell ist und der andere nicht.

    
Jason Williams 06.12.2009 20:39
quelle
0

Nein, sollte es nicht.

Wenn Sie eine virtuelle Methode aufrufen, ist es egal, um welche Art von Referenz es sich handelt. Die Methode, die aufgerufen wird, wird durch den tatsächlichen Typ des Objekts bestimmt, nicht durch den Typ der Referenz.

Wenn Sie eine Instanz der Klasse B erstellen, ist der tatsächliche Typ des Objekts B . Der Grund dafür, dass "This is class A." gedruckt wird, ist, dass Sie die Methode ToString in der Klasse B nicht überschrieben haben. Sie haben sie mit dem Schlüsselwort new schattiert. Daher hat die B -Klasse zwei ToString -Methoden, eine von der Klasse A geerbte und eine, die sie schattiert. Wenn Sie eine A -Referenz verwenden, um die ToString -Methode aufzurufen, wird die geerbte Methode aufgerufen. Wenn Sie jedoch eine B -Referenz verwendet hätten, um sie aufzurufen, würde die Shadowing-Methode aufgerufen und "This is class B." ausgedruckt.

Auch wenn Sie die Methode ToString in der Klasse B überschreiben, anstatt sie zu spiegeln, würde% code_de% unabhängig vom Typ der Referenz ausgegeben.

    
Guffa 06.12.2009 20:46
quelle