Sie werden sehr selten "neu" verwenden, um ein Basisklassenmitglied zu maskieren.
Es wird hauptsächlich für die Fälle verwendet, in denen die abgeleitete Klasse zuerst das Member hatte, und dann wurde es zur Basisklasse hinzugefügt --- derselbe Name für einen anderen Zweck. Der new
ist da, dem Sie anerkennen, dass Sie wissen, dass Sie es anders verwenden. Wenn ein Basiselement in C ++ hinzugefügt wird, fügt es die vorhandene Methode nur im Hintergrund in die Vererbungskette ein. In C # müssen Sie zwischen new
und override
wählen, um Ihnen zu zeigen, was passiert.
Es wird nicht nur zum Maskieren verwendet. Es bricht tatsächlich die Vererbungskette. Wenn Sie also die Basisklassenmethode aufrufen, wird die Methode in der abgeleiteten Klasse nicht aufgerufen (nur die in der Basisklasse).
Sie erstellen im Wesentlichen eine neue -Methode, die nichts mit der Basisklassenmethode zu tun hat. Daher das Schlüsselwort "new".
Das Schlüsselwort "new" kann verwendet werden, wenn Sie eine Methode mit der gleichen Signatur wie eine Basistyp-Methode, aber mit einem anderen Rückgabetyp definieren möchten.
Die einzigen gültigen sicheren Beispiele, auf die ich gestoßen bin, sind spezifischer mit Rückgabetypen oder bieten einen Set-Accessor für eine Eigenschaft . Ich sage nicht, dass das die einzigen sind, aber das ist alles, was ich gefunden habe.
Angenommen, Sie haben eine sehr einfache Basis, die wie folgt aussieht:
%Vor%Sie könnten eine Ableitung haben, die eher so aussieht:
%Vor% Wenn angenommen wird, dass Geschäftsregeln es einem bestimmten Derived erlauben, einen änderbaren Namen zu haben, glaube ich, dass dies akzeptabel ist. Das Problem mit new
besteht darin, dass sich das Verhalten ändert, je nachdem, welcher Typ der Instanz angezeigt wird. Zum Beispiel, wenn ich sagen würde:
In diesem trivialen Beispiel geht es uns gut. Wir überschreiben das Verhalten mit new
, aber nicht auf brechende Weise. Das Ändern der Rückgabetypen erfordert etwas mehr Finesse. Wenn Sie nämlich new
verwenden, um einen Rückgabetyp für einen abgeleiteten Typ zu ändern, sollten Sie nicht zulassen, dass dieser Typ von der Basis festgelegt wird. Schau dir dieses Beispiel an:
Wenn ich set Child
für die Klasse Base
hätte, könnte ich ein Casting-Problem in der Klasse Derived
haben. Ein anderes Beispiel:
Ich kann keine Geschäftsregeln brechen, indem ich alle meine Derived
-Klassen als Bases behandle, es ist einfach praktisch, check und cast nicht einzugeben.
Ich habe gerade gelernt, wie man ein Basisklassenmitglied maskiert (mit new)
Zu Ihrer Information: Diese Funktion wird normalerweise "Verbergen" und nicht "Maskieren" genannt. Ich denke an "Maskierung" als Clearing-Bits in einem Bit-Array.
Ich vermisse den Punkt, warum ich das machen möchte.
Normalerweise möchten Sie nicht. Aus einigen Gründen, um diese Funktion zu verwenden und nicht zu verwenden, siehe meinen Artikel zu diesem Thema von 2008:
Bietet uns die Maskierung ein gewisses Maß an Schutz, wie es bei der Kapselung der Fall ist?
Nein, tut es nicht.
Was Sie meinen, heißt Name Verbergen . Es ist hauptsächlich ein Komfortmerkmal. Wenn Sie von einer Klasse erben, für die Sie die Quelle nicht mithilfe von new
steuern, können Sie das Verhalten einer Methode ändern, auch wenn sie nicht als virtuell deklariert wurde (oder die Signatur vollständig ändern, wenn sie virtuell ist). Das Schlüsselwort new
unterdrückt einfach eine Compiler-Warnung. Sie informieren den Compiler grundsätzlich darüber, dass Sie die Methode absichtlich vor einer übergeordneten Klasse verbergen.
Delphi hatte das Schlüsselwort reintroduce
aus dem gleichen Grund.
Was kauft dir das anders als eine unterdrückte Warnung? Nicht viel. Sie können nicht auf die new
-Methode von einer übergeordneten Klasse zugreifen. Sie können über eine Schnittstelle darauf zugreifen, wenn Ihre untergeordnete Klasse die Schnittstelle direkt implementiert (so als ob sie sie von ihrer übergeordneten Klasse erben würde). Sie können das Mitglied der übergeordneten Klasse immer noch vom untergeordneten Element aufrufen. Alle zusätzlichen Nachkommen Ihrer Klasse erben das new
-Member und nicht dasjenige im übergeordneten Element.
Dies wird tatsächlich als Verstecken von Elementen bezeichnet. Es gibt ein paar häufige Szenarien, in denen dies angemessen genutzt werden kann.
In Bezug auf den ersten Punkt ... ist es möglich, dass ein Autor einer Basisklasse später ein Mitglied mit demselben Namen wie ein existierendes Mitglied in einer abgeleiteten Klasse hinzufügen kann. Der Basisklassenautor hat möglicherweise keine Kenntnis der abgeleiteten Klassen, und daher wird nicht erwartet, dass sie Namenskollisionen vermeiden sollte. C # unterstützt die unabhängige Entwicklung von Klassenhierarchien mithilfe der Verbergungsmechanismen.
In Bezug auf den zweiten Punkt ... möchten Sie vielleicht, dass eine Klasse eine Schnittstelle implementiert, die eine bestimmte Methodensignatur diktiert, und Sie also nur bestimmte Instanzen eines bestimmten Typs zurückgeben, während Sie gleichzeitig diesen Typ unterklassifiziert haben und dies auch tun würden wirklich wie Anrufer, um den konkreten Typ stattdessen zu sehen. Betrachten Sie dieses Beispiel.
%Vor%Tags und Links class c# mask encapsulation