Pourquoi ne puis-je pas avoir de méthodes statiques abstraites en C

J'ai travaillé 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 messages sur le sujet, et cela avait du sens, mais y a-t-il une belle explication claire ?

请先 登录 后评论

5 réponses

David Wengier

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, pour un instant, hériter de méthodes statiques. Imaginez ce scénario :

public static class Base
{
    public static virtual int GetNumber() { return 5; }
}

public static class Child1 : Base
{
    public static override int GetNumber() { return 1; }
}

public static class Child2 : Base
{
    public static override int GetNumber() { return 2; }
}

Si vous appelez Base.GetNumber(), quelle méthode serait 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 sont simplement des méthodes qui n'ont pas de corps et ne peuvent donc pas être appelées.

请先 登录 后评论
Rytmis

Pour ajouter aux explications précédentes, les appels de méthode statique sont liés à une méthode spécifique au moment de la compilation, ce qui exclut plutôt le comportement polymorphe.

请先 登录 后评论
Lasse Vågsæther Karlsen

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 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 :

public class A
{
    public static void Test()
    {
    }
}

public class B : A
{
}

Si vous appelez B.Test, comme ceci :

class Program
{
    static void Main(string[] args)
    {
        B.Test();
    }
}

Ensuite, le code réel à l'intérieur de la méthode Main est le suivant :

.entrypoint
.maxstack 8
L0000: nop 
L0001: call void ConsoleApplication1.A::Test()
L0006: nop 
L0007: ret 

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 faire référence à une variable à un type et non à un objet, vous auriez plus d'utilité pour les méthodes statiques virtuelles et donc abstraites (et aussi constructeurs), mais ils ne sont pas disponibles et les appels statiques ne sont donc pas virtuels dans .NET.

Je me rends compte que les concepteurs 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 toujours à écrire une sorte de nom de classe là.

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 voulez donc appeler la bonne méthode pour l'objet courant que vous avez dans la variable. Avec les méthodes statiques, vous devez de toute façon passer par un nom de classe, de sorte que 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.

请先 登录 后评论
Fabio Gomes

En fait, nous redéfinissons les méthodes statiques (dans 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 :

class function AvailableObjects: string; override;
begin
  Result := 'Object1, Object2';
end; 

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 à maintenir que d'avoir une application serveur différente pour chaque client.

J'espère que l'exemple était clair.

请先 登录 后评论
AMing

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 abstraite statique (ou abstraite statique).

请先 登录 后评论
  • 29 abonnés
  • 0 favoris,332 Feuilleter
  • lomaxx posée à 2023-03-05 06:24