2012-03-28 10 views
12

Wie verhindere ich eine Methode aus in einer abgeleiteten Klasse überschrieben werden?Verhindern eines Verfahrens von in C# überschrieben wird

In Java konnte ich dies tun, indem Sie den Modifikator final auf die Methode, die ich verhindern möchte, zu übersteuern.

Wie erreiche ich das gleiche in C#?
Ich bin mir bewusst, sealed verwenden, aber anscheinend kann ich es nur mit dem override Schlüsselwort verwenden?

class A 
{ 
    public void methodA() 
    { 
     // Code. 
    } 

    public virtual void methodB() 
    { 
     // Code. 
    } 
} 

class B : A 
{ 
    sealed override public void methodB() 
    { 
     // Code. 
    } 
} 

So im obigen Beispiel kann ich die methodB() verhindern, durch irgendwelche Klassen überschrieben wird von der Klasse abgeleitet B, aber wie kann ich verhindern, Klasse B von Überschreiben der methodB() in erster Linie?

Update: Ich verpasste das virtual Schlüsselwort in der methodB() Erklärung auf Klasse A, als ich diese Frage gepostet. Korrigiert es.

+0

Ist dies ein neues Feature in C# 4, um eine Methode zu versiegeln? –

+0

Wenn Sie die Methode nicht schon überschreiben, dann dekorieren Sie sie nicht mit 'virtual', dann wird alles andere nicht berücksichtigt, um die Methode an Ihren Typ zu binden. –

+0

Ich glaube, dass Ihre Methoden in Klasse A "virtuell" sein sollten, wenn Sie sie überschreiben wollen. – CAbbott

Antwort

21

Sie brauchen nichts zu tun. Der Modifizierer virtual gibt an, dass eine Methode überschrieben werden kann. Wenn man es auslässt, bedeutet das, dass die Methode "endgültig" ist.

Konkret muss eine Methode virtual, abstract oder override lauten, damit sie überschrieben wird.

das new Schlüsselwort wird die Basisklassenmethode erlauben versteckt werden, aber es wird immer noch nicht das heißt außer Kraft setzen, wenn Sie anrufen A.methodB() Sie die Basisklassenversion bekommen, aber wenn Sie B.methodB() nennen Sie die neue Version bekommen.

+0

Es ist frustrierend in einer Sprache, die so viele Dinge explizit aussprechen lässt, es gibt kein Schlüsselwort, um explizit zu sagen: "Das ist nicht gemein, jemals übersteuert zu werden "Wenn Sie es nicht versehentlich später virtuell machen, ohne darüber nachzudenken, warum es nicht an erster Stelle war. –

11

Wie Sie erwähnt, kann man durch weitere überwiegendes von MethodB in Klasse B verhindern Verwendung sealedmitoverride

class B : A 
{ 
    public sealed override void methodB() 
    { 
     Console.WriteLine("Class C cannot override this method now"); 
    } 
} 

Verwendung des sealed Modifikator zusammen mitoverride verhindert eine abgeleitete Klasse von der weiteren Übergeordnetes Methode.

Wenn Sie nicht möchten, dass methodB in Klasse A von einer untergeordneten Klasse überschrieben wird, markieren Sie diese Methode nicht virtual. Einfach entfernen. Schlüsselwort virtual ermöglicht das Verfahren

public void methodA() 
{  
} 

Verwenden sealed Stichwort auf Ihren Klassen in untergeordneten Klassen außer Kraft gesetzt werden, um einen weiteren übergeordnet der Klasse

+3

Die Verwendung des versiegelten Modifizierers verhindert, dass eine Klasse von "Klasse A" abgeleitet wird. Das ist nicht gefragt. –

+0

@KendallFrey: Der Titel der Frage ließ mich denken, dass es darum geht, weiteres Überschreiben zu verhindern. Danke – Shyju

+7

@KendallFrey 'versiegelt' kann auf Methoden angewendet werden, vorausgesetzt, dass sie auch überschrieben werden. Es verhindert * weiter * das Überschreiben in abgeleiteten Klassen (wie Shyju darauf hinweist). – dlev

1

in einer Basisklasse wird die versiegelte Schlüsselwort, eine Klasse zu verhindern, dass abgeleitet, aber in vererbten Klassen können sie verwendet werden, zu verhindern, dass eine andere Klasse von ererbten Überschreiben der Methode nur verwendet.

Um eine Basisklassenmethode aus außer Kraft gesetzt werden, einfach nicht geben Sie es als virtuelle zu verhindern. In dem von Ihnen bereitgestellten Beispiel konnte Klasse B methodB nicht überschreiben, da methodB in der ursprünglichen Klasse nicht als virtuell markiert war.

diese kompilieren:

class A 
{ 
    public virtual void methodA() 
    { 
     //code 
    } 
    public virtual void methodB() 
    { 
     //code 
    } 
} 
class B:A 
{ 
    public override void methodB() 
    { 
     //code 
    } 
} 

dies nicht:

class A 
{ 
    public void methodA() 
    { 
     //code 
    } 
    public void methodB() 
    { 
     //code 
    } 
} 
class B:A 
{ 
    public override void methodB() 
    { 
     //code 
    } 
} 

editierte: geklärt und korrigiert meine ursprüngliche Aussage über das Schlüsselwort

versiegelt
+2

"versiegelt" kann tatsächlich für einzelne Methoden verwendet werden, es ist nur so, dass "versiegelt" nicht bei der höchsten Implementierung der Methode verwendet werden kann; Es muss für eine Methode verwendet werden, die eine Basisimplementierung überschreibt. Im Grunde negiert es das "virtuelle" Schlüsselwort von höheren Vererbungsebenen, wenn es weiter abgeleitet wird. Also, du liegst falsch, dass es nicht benutzt werden kann, aber es löst sein Problem sowieso nicht – KeithS

+0

@KeithS danke dafür. Ich habe noch nie gesehen, dass es früher benutzt wurde, um Methoden zu versiegeln und zu übergehen, aber danke, dass du mir etwas Neues beigebracht hast. Ich habe meine Antwort passend editiert – psubsee2003

5

In C#, eine Funktion nicht virtual markiert (die auch Überschreibungen virtueller Funktionen enthält) ist effektiv versiegelt und kann nicht überschrieben werden. Ihr Beispielcode wird also nicht kompiliert, da das Schlüsselwort override nicht gültig ist, es sei denn, es gibt eine Methode, die in einer Basisklasse mit der gleichen Signatur als virtuell markiert ist. Wenn A.methodB() als virtuell markiert wurde, dann könnten Sie die Methode von A überschreiben, aber verhindern, dass sie in indirekt abgeleiteten Klassen weiter überschrieben wird, indem Sie das Schlüsselwort sealed genau so verwenden, wie Sie es gezeigt haben.

Eine Sache zu beachten ist, dass, während Methode überschreiben kann verhindert werden, Methode Hiding kann nicht. Angesichts Ihrer aktuelle Definition der Klasse A ist die folgende Definition der Klasse B legal und es gibt nichts, was man dagegen tun kann:

class B:A 
{ 
     public new void methodB() 
      { 
        //code 
      } 
    } 

Das new Stichwort im Grunde „bricht“ die Vererbung/zwingende Hierarchie, wie es zu diesem gehört Methode; Jede Bezugnahme auf eine Klasse B, die als Klasse B behandelt wird (oder ein weiterer abgeleiteter Typ), verwendet die Implementierung aus Klasse B und ignoriert diejenige aus Klasse A, es sei denn, die Implementierung von B ruft sie spezifisch zurück. Wenn Sie jedoch eine Instanz der Klasse B als Klasse A behandeln (indem Sie sie übergeben oder als Parameter übergeben), wird die Implementierung "new" ignoriert.

Dies unterscheidet sich vom Überschreiben, wenn eine Klasse B, die als Klasse A behandelt wird und eine virtuelle Methode wirklich überschreibt, B weiterhin die Methode überschreiben würde. Verstehen Sie auch, dass das Verstecken von Methoden gefolgert wird (obwohl Sie eine Compiler-Warnung erhalten); Wenn Sie eine Methode mit derselben Signatur in einer abgeleiteten Klasse deklarieren und weder new noch override angeben, wird die Basisklassenmethode ausgeblendet.

+0

Tolle Infos zum Modifikator 'new'. Wusste das überhaupt nicht. – CAbbott

Verwandte Themen