Existe-t-il un moyen de remplacer une méthode non virtuelle? ou quelque chose qui donne des résultats similaires (autre que la création d'une nouvelle méthode pour appeler la méthode souhaitée)?
Je voudrais remplacer une méthode de Microsoft.Xna.Framework.Graphics.GraphicsDevice
avec les tests unitaires à l'esprit.
c#
overriding
overloading
zfedoran
la source
la source
Réponses:
Non, vous ne pouvez pas remplacer une méthode non virtuelle. La chose la plus proche que vous pouvez faire est de cacher la méthode en créant une
new
méthode avec le même nom, mais ce n'est pas conseillé car cela enfreint les bons principes de conception.Mais même le fait de cacher une méthode ne vous donnera pas le temps d'exécution d'une distribution polymorphe des appels de méthode comme le ferait un véritable appel de méthode virtuelle. Prenons cet exemple:
Dans cet exemple, les deux appels à la
M
méthode printFoo.M
. Comme vous pouvez le voir cette approche ne vous permet d'avoir une nouvelle mise en œuvre d'une méthode aussi longtemps que la référence à cet objet est du type dérivé correct , mais cachant une méthode de base ne polymorphisme de rupture.Je vous recommande de ne pas masquer les méthodes de base de cette manière.
J'ai tendance à me rallier à ceux qui favorisent le comportement par défaut de C # selon lequel les méthodes ne sont pas virtuelles par défaut (par opposition à Java). J'irais même plus loin et dire que les classes devraient également être scellées par défaut. L'héritage est difficile à concevoir correctement et le fait qu'il existe une méthode qui n'est pas marquée comme virtuelle indique que l'auteur de cette méthode n'a jamais eu l'intention de remplacer la méthode.
Edit: "expédition polymorphe du temps d'exécution" :
Ce que je veux dire par là, c'est le comportement par défaut qui se produit au moment de l'exécution lorsque vous appelez des méthodes virtuelles. Disons par exemple que dans mon exemple de code précédent, plutôt que de définir une méthode non virtuelle, j'ai en fait défini une méthode virtuelle et une véritable méthode surchargée.
Si je devais appeler
b.Foo
dans ce cas, le CLR déterminerait correctement le type d'objet vers lequel lab
référence pointeBar
et enverrait l'appel deM
manière appropriée.la source
Non, tu ne peux pas.
Vous ne pouvez remplacer qu'une méthode virtuelle - voir le MSDN ici :
la source
Si la classe de base n'est pas scellée, vous pouvez en hériter et écrire une nouvelle méthode qui cache celle de base (utilisez le mot-clé "new" dans la déclaration de méthode). Sinon, vous ne pouvez pas le remplacer car ce n'était jamais l'intention des auteurs d'origine de le remplacer, d'où la raison pour laquelle il n'est pas virtuel.
la source
Je pense que vous obtenez une surcharge et une substitution confuses, la surcharge signifie que vous avez deux méthodes ou plus avec le même nom mais des ensembles de paramètres différents tout en remplaçant signifie que vous avez une implémentation différente pour une méthode dans une classe dérivée (remplaçant ou modifiant ainsi le comportement dans sa classe de base).
Si une méthode est virtuelle, vous pouvez la remplacer à l'aide du mot clé override dans la classe dérivée. Cependant, les méthodes non virtuelles ne peuvent masquer l'implémentation de base qu'en utilisant le mot clé new à la place du mot clé override. La route non virtuelle est inutile si l'appelant accède à la méthode via une variable tapée comme type de base car le compilateur utiliserait une distribution statique à la méthode de base (ce qui signifie que le code de votre classe dérivée ne sera jamais appelé).
Il n'y a jamais rien qui vous empêche d'ajouter une surcharge à une classe existante, mais seul le code qui connaît votre classe pourra y accéder.
la source
Vous ne pouvez pas remplacer la méthode non virtuelle d'une classe en C # (sans pirater CLR), mais vous pouvez remplacer toute méthode d'interface implémentée par la classe. Considérez que nous avons non scellé
Et voici la démo
la source
Dans le cas où vous héritez d'une classe non dérivée, vous pouvez simplement créer une super-classe abstraite et en hériter en aval à la place.
la source
Vous ne pouvez pas remplacer une méthode non virtuelle. Cependant vous pouvez utiliser le
new
mot-clé modificateur pour obtenir des résultats similaires:Vous voudrez également vous assurer que le modificateur d'accès est également le même, sinon vous n'obtiendrez pas d'héritage sur toute la ligne. Si une autre classe hérite du mot
Class1
-new
clé inClass1
n'affectera pas les objets qui en héritent, sauf si le modificateur d'accès est le même.Si le modificateur d'accès n'est pas le même:
... versus si le modificateur d'accès est le même:
Comme indiqué dans une réponse précédente, ce n'est pas un bon principe de conception.
la source
Il existe un moyen d'y parvenir en utilisant une classe abstraite et une méthode abstraite.
Considérer
Maintenant, si vous souhaitez avoir différentes versions de la méthode MethodToBeTested (), changez Class Base en une classe abstraite et la méthode MethodToBeTested () en tant que méthode abstraite
Avec abstract void MethodToBeTested () vient un problème; la mise en œuvre a disparu.
Par conséquent, créez un
class DefaultBaseImplementation : Base
pour avoir l'implémentation par défaut.Et créer un autre
class UnitTestImplementation : Base
pour implémenter le test unitaire.Avec ces 2 nouvelles classes, la fonctionnalité de classe de base peut être remplacée.
Maintenant, vous avez 2 classes implémentées (remplacement)
MethodToBeTested()
.Vous pouvez instancier la classe (dérivée) selon les besoins (c'est-à-dire avec l'implémentation de base ou avec l'implémentation de test unitaire).
la source