2010-05-31 5 views
16

Ich bin über dieses "Feature" von C# - die Basisklasse gestolpert, die Schnittstellenmethoden implementiert, muss nicht davon abgeleitet werden.Warum darf eine Basisklasse in C# einen Schnittstellenvertrag implementieren, ohne von ihm zu erben?

Beispiel:

public interface IContract 
{ 
    void Func(); 
} 

// Note that Base does **not** derive from IContract 
public abstract class Base 
{ 
    public void Func() 
    { 
     Console.WriteLine("Base.Func"); 
    } 
} 

// Note that Derived does *not* provide implementation for IContract 
public class Derived : Base, IContract 
{ 
} 

Was passiert, ist, dass Derived magisch zieht an eine öffentliche Methode, Base.Func und entscheidet, dass es IContract.Func umsetzt.

Was ist der Grund für diese Magie?

IMHO: diese "Quasi-Implementierung" -Funktion ist sehr unintuitiv und machen Code-Inspektion viel schwieriger. Was denken Sie?

+1

Ich 'denke', dass Sie mit der expliziten Implementierung der Schnittstelle in abgeleiteten Klasse den Nebeneffekt umgehen können. – kenny

+3

Das macht für mich Sinn. Wenn Derived IContract erbt, bedeutet das, dass es Func() bereitstellt, was es tut. Dass es durch Vererbung geschieht, ist nur nebensächlich. Beachten Sie, dass Base * nicht * IContract implementiert - wenn Sie versuchen würden, eine Base nach IContract zu konvertieren, würde dies fehlschlagen. – allonym

Antwort

28

Der Grund dafür ist, dass Ihr Kommentar einfach falsch ist:

// dass Hinweis Abgeleitet ist nicht zur Umsetzung bieten IContract

Sicher, es tut. Folge der Logik durch.

  • Abgeleitet muss ein öffentliches Mitglied sein, das jedem Mitglied von IContract entspricht.
  • Alle vererbbaren Mitglieder einer Basisklasse sind auch Mitglieder einer abgeleiteten Klasse; das ist die Definition der Vererbung.
  • Daher bietet Derived eine Implementierung für IContract; sein geerbtes Mitglied ist ein Mitglied, das die Anforderung erfüllt
  • Daher kein Fehler.

diese Funktion ist sehr-unintuitive und Code-Inspektion viel schwieriger machen. Was denken Sie?

Ich denke, Sie sollten die Funktion nicht verwenden, wenn Sie es nicht mögen. Wenn Sie es verwirrend und komisch finden, Code zu lesen, der diese Funktion verwendet, dann ermutigen Sie Ihre Mitarbeiter, die diese Funktion verwenden, damit aufzuhören.

Wie unterscheidet sich dieses Feature von allen anderen Features, bei denen eine Methode aus einer Basisklasse aus einer abgeleiteten Klasse verwendet wird? Es gibt eine Reihe verschiedener Möglichkeiten, wie eine Methode aus einer Basisklasse in einer abgeleiteten Klasse verwendet oder erwähnt werden kann: Methodenaufrufe, Überschreibungen, Methodengruppenumwandlungen und so weiter.

Darüber hinaus ist dies relativ ein einfacher, einfacher Fall. Wenn Sie sich wirklich über die verwirrende Interface-Semantik in C# beschweren möchten, würde ich mich damit beschämen, über Semantik der Schnittstellen-Reimplementierung zu klagen. Das ist der, der die Nudeln der Leute wirklich zu backen scheint. Ich muss das Ding immer in der Spezifikation sehen, um sicherzugehen, dass ich die Semantik richtig verstehe.

+0

Vielen Dank für die ausführliche Antwort! Ich * verstehe * * wie * es funktioniert, aber IMHO die Art, wie es funktioniert, ist aus einer Reihe von Gründen kontraintuitiv: (1) liest man zuerst das Preisschild und zahlt dann, so wie man zuerst * erklärt * und nur * nach * * implementiert * etw. (2) Abgeleitet ist ein IContract, implementiert es nicht, aber verwendet Base, um IContract zu implementieren, das ist kein IContract selbst (3) Durch das Lesen von Code für Base gibt es keine Möglichkeit zu entscheiden, ob Base.Func mit IContract verwandt ist .Func (die Beziehung deklarieren/implementieren). (4) Das Ändern von Base.Func wird einen Kompilierungsfehler erzeugen, der Base nicht einmal erwähnt – etarassov

+0

"Ich denke, dass Sie die Funktion nicht verwenden sollten, wenn Sie es nicht mögen." - 100% stimmen zu. Leider könnten andere Leute es (oder die vorhandene Codebasis) benutzen, was den Code schwer lesbar macht. Die wirklich großartige Sprache führt den Entwickler dazu, guten Code zu schreiben (idealerweise würde er es erzwingen). C# (eine sehr nette Sprache) würde nur von Vorteil sein, wenn diese Funktion entfernt wird. Aber es wäre wirklich schwer und schmerzhaft ... Genau wie bei Verschlüssen innerhalb einer Foreach mit der Loop-Variable. Trotzdem danke für den Link zur "Interface Reimplementation Semantics"! – etarassov

10

Warum denken Sie, dass das seltsam und unnatürlich ist? Jedes öffentliche Mitglied der Basisklasse ist auch ein öffentliches Mitglied der abgeleiteten Klasse. Es gibt also keinen Widerspruch. Irgendwie können Sie die Schnittstelle explizit implementieren, wenn Sie möchten.

+1

IMHO diese Art von Funktion fügt der Sprache die unnötige Komplexität hinzu. Der einfache und natürliche Weg wäre, die Basis von IContract abzuleiten, um explizit anzugeben, dass sie es implementiert. Menschen sind einfache Wesen - wir sind nicht in der Lage, den gesamten Code sofort zu analysieren und den Vererbungsgraphen zu referenzieren, um zu verstehen, dass IContract.Func und Base.Func verwandt sind (Umbenennung von IContract.Func muss man * Base * umbenennen) .Func). Es wird noch komplizierter, wenn sich alle drei Klassen in verschiedenen Projekten/Lösungen befinden. – etarassov

+0

Kurz gesagt - diese Funktion * ist schlecht *, weil die Lesbarkeit des * Codes stark leidet *. Ein Programmierer (möglicherweise) muss jede Basisklasse durchlaufen, um eine Schnittstellenimplementierung zu finden, sogar über die Basisklassen, die völlig unabhängig von der Schnittstelle sind. – etarassov

+1

ok Ich werde versuchen zu erklären: Die Situation, die Sie beschreiben möchten, ist selten und unnatürlich. Vor allem dieser - "Es wird noch komplizierter, wenn alle drei Klassen in verschiedenen Projekten/Lösungen angesiedelt sind." Auch hier können Sie die Schnittstelle explizit implementieren, so dass Sie jegliche Kollisionen mit Basisklassenmethoden vermeiden. – Voice

Verwandte Themen