J'ai travaillé pas mal avec des fournisseurs ces derniers temps, et je suis tombé sur une situation intéressante où je voulais avoir une classe abstraite qui avait une méthode statique abstraite. J'ai lu quelques articles sur le sujet, et cela avait du sens, mais y a-t-il une bonne explication claire?
c#
.net
language-design
lomaxx
la source
la source
Réponses:
Les méthodes statiques ne sont pas instanciées en tant que telles, elles sont simplement disponibles sans référence d'objet.
Un appel à une méthode statique se fait via le nom de la classe, pas via une référence d'objet, et le code IL (Intermediate Language) pour l'appeler appellera la méthode abstraite via le nom de la classe qui l'a définie, pas nécessairement le nom de la classe que vous avez utilisée.
Laissez-moi vous montrer un exemple.
Avec le code suivant:
Si vous appelez B.Test, comme ceci:
Ensuite, le code réel à l'intérieur de la méthode Main est le suivant:
Comme vous pouvez le voir, l'appel est fait à A.Test, car c'est la classe A qui l'a défini, et non à B.Test, même si vous pouvez écrire le code de cette façon.
Si vous aviez des types de classe , comme dans Delphi, où vous pouvez créer une variable faisant référence à un type et non à un objet, vous auriez plus d'utilité pour les méthodes statiques virtuelles et donc abstraites (et aussi les constructeurs), mais elles ne sont pas disponibles et ainsi les appels statiques ne sont pas virtuels dans .NET.
Je me rends compte que les concepteurs d'IL pourraient permettre au code d'être compilé pour appeler B.Test, et résoudre l'appel au moment de l'exécution, mais ce ne serait toujours pas virtuel, car vous auriez encore à écrire une sorte de nom de classe là-bas.
Les méthodes virtuelles, et donc abstraites, ne sont utiles que lorsque vous utilisez une variable qui, à l'exécution, peut contenir de nombreux types d'objets différents, et que vous souhaitez donc appeler la bonne méthode pour l'objet actuel que vous avez dans la variable. Avec les méthodes statiques, vous devez de toute façon passer par un nom de classe, donc la méthode exacte à appeler est connue au moment de la compilation car elle ne peut pas et ne changera pas.
Ainsi, les méthodes statiques virtuelles / abstraites ne sont pas disponibles dans .NET.
la source
Test()
estA
plutôt que abstraite et potentiellement définie dansB
. \Car
type avec uneCreateFromDescription
méthode de fabrique statique virtuelle , alors le code qui acceptait unCar
type générique -constrainedT
pourrait appelerT.CreateFromDescription
pour produire une voiture de typeT
. Une telle construction pourrait être assez bien supportée dans le CLR si chaque type qui définissait une telle méthode contenait une instance de singleton statique d'une classe imbriquée générique qui contenait les méthodes «statiques» virtuelles.Les méthodes statiques ne peuvent pas être héritées ou remplacées, et c'est pourquoi elles ne peuvent pas être abstraites. Comme les méthodes statiques sont définies sur le type, et non sur l'instance, d'une classe, elles doivent être appelées explicitement sur ce type. Ainsi, lorsque vous souhaitez appeler une méthode sur une classe enfant, vous devez utiliser son nom pour l'appeler. Cela rend l'héritage non pertinent.
Supposons que vous puissiez, pendant un moment, hériter des méthodes statiques. Imaginez ce scénario:
Si vous appelez Base.GetNumber (), quelle méthode sera appelée? Quelle valeur renvoyée? Il est assez facile de voir que sans créer d'instances d'objets, l'héritage est plutôt difficile. Les méthodes abstraites sans héritage ne sont que des méthodes qui n'ont pas de corps et ne peuvent donc pas être appelées.
la source
int DoSomething<T>() where T:Base {return T.GetNumber();}
. Il semblerait utile deDoSomething<Base>()
pouvoir en renvoyer cinq, tandisDoSomething<Child2>()
que d'en renvoyer deux. Une telle capacité serait non seulement utile pour les exemples de jouets, mais aussi pour quelque chose commeclass Car {public static virtual Car Build(PurchaseOrder PO);}
, où chaque classe dérivantCar
devrait définir une méthode qui pourrait construire une instance à partir d'un bon de commande.Un autre répondant (McDowell) a déclaré que le polymorphisme ne fonctionne que pour les instances d'objets. Cela devrait être nuancé; il existe des langages qui traitent les classes comme des instances de type "Class" ou "Metaclass". Ces langages prennent en charge le polymorphisme pour les méthodes d'instance et de classe (statiques).
C #, comme Java et C ++ avant lui, n'est pas un tel langage; le
static
mot-clé est utilisé explicitement pour indiquer que la méthode est liée statiquement plutôt que dynamique / virtuelle.la source
Voici une situation où il y a certainement un besoin d'héritage pour les champs et méthodes statiques:
la source
legs
doit être une propriété abstraite statique.Pour ajouter aux explications précédentes, les appels de méthodes statiques sont liés à une méthode spécifique au moment de la compilation , ce qui exclut plutôt un comportement polymorphe.
la source
Nous remplaçons en fait les méthodes statiques (en delphi), c'est un peu moche, mais cela fonctionne très bien pour nos besoins.
Nous l'utilisons pour que les classes puissent avoir une liste de leurs objets disponibles sans l'instance de classe, par exemple, nous avons une méthode qui ressemble à ceci:
C'est moche mais nécessaire, de cette façon nous pouvons instancier juste ce qui est nécessaire, au lieu d'avoir toutes les classes instanciées juste pour rechercher les objets disponibles.
C'était un exemple simple, mais l'application elle-même est une application client-serveur qui a toutes les classes disponibles sur un seul serveur, et plusieurs clients différents qui pourraient ne pas avoir besoin de tout ce que le serveur a et n'auront jamais besoin d'une instance d'objet.
C'est donc beaucoup plus facile à gérer que d'avoir une application serveur différente pour chaque client.
J'espère que l'exemple était clair.
la source
Les méthodes abstraites sont implicitement virtuelles. Les méthodes abstraites nécessitent une instance, mais les méthodes statiques n'ont pas d'instance. Ainsi, vous pouvez avoir une méthode statique dans une classe abstraite, elle ne peut tout simplement pas être statique abstraite (ou statique abstraite).
la source