Pourquoi ne puis-je pas hériter de classes statiques?

J’ai plusieurs classes qui n’ont pas vraiment besoin d’un état. Du sharepoint vue de l’organisation, j’aimerais les hiérarchiser.

Mais il semble que je ne puisse pas déclarer l’inheritance pour les classes statiques.

Quelque chose comme ca:

public static class Base { } public static class Inherited : Base { } 

ne fonctionnera pas.

Pourquoi les concepteurs du langage ont-ils fermé cette possibilité?

Citation d’ ici :

C’est en fait par conception. Il ne semble y avoir aucune bonne raison d’hériter d’une classe statique. Il a des membres statiques publics auxquels vous pouvez toujours accéder via le nom de la classe lui-même. Les seules raisons pour lesquelles j’ai hérité de choses statiques ont été les mauvaises, telles que la sauvegarde de deux caractères.

Il peut y avoir des raisons de considérer des mécanismes pour amener les membres statiques directement dans la scope (et nous allons en tenir compte après le cycle de produit Orcas), mais l’inheritance de classe statique n’est pas la solution: c’est le mauvais mécanisme à utiliser. uniquement pour les membres statiques qui résident dans une classe statique.

(Mads Torgersen, PM du langage C #)

Autres avis de channel9

L’inheritance dans .NET ne fonctionne que sur la base de l’instance. Les méthodes statiques sont définies au niveau du type et non au niveau de l’instance. C’est pourquoi la substitution ne fonctionne pas avec les méthodes / propriétés / événements statiques …

Les méthodes statiques ne sont conservées qu’une seule fois en mémoire. Il n’y a pas de table virtuelle, etc. créée pour eux.

Si vous appelez une méthode d’instance dans .NET, vous lui donnez toujours l’instance actuelle. Ceci est masqué par le runtime .NET, mais cela arrive. Chaque méthode d’instance a comme premier argument un pointeur (référence) sur l’object sur lequel la méthode est exécutée. Cela ne se produit pas avec les méthodes statiques (telles qu’elles sont définies au niveau du type). Comment le compilateur doit-il décider de sélectionner la méthode à appeler?

(littleguru)

Et comme une idée précieuse, littleguru a une «solution» partielle à ce problème: le modèle Singleton .

La principale raison pour laquelle vous ne pouvez pas hériter d’une classe statique est qu’elles sont abstraites et scellées (cela empêche également la création de toute instance).

Donc ça:

 static class Foo { } 

comstack à cette IL:

 .class private abstract auto ansi sealed beforefieldinit Foo extends [mscorlib]System.Object { } 

Pensez-y de cette façon: vous accédez aux membres statiques via le nom du type, comme ceci:

 MyStaticType.MyStaticMember(); 

Si vous deviez hériter de cette classe, vous devriez y accéder via le nouveau nom de type:

 MyNewType.MyStaticMember(); 

Ainsi, le nouvel élément n’a aucune relation avec l’original lorsqu’il est utilisé dans le code. Il n’y aurait aucun moyen de tirer parti d’une relation d’inheritance comme le polymorphism.

Vous pensez peut-être que vous souhaitez simplement étendre certains des éléments de la classe d’origine. Dans ce cas, rien ne vous empêche d’utiliser simplement un membre de l’original dans un type entièrement nouveau.

Vous souhaitez peut-être append des méthodes à un type statique existant. Vous pouvez le faire déjà via les méthodes d’extension.

Peut-être voulez-vous pouvoir passer un Type statique à une fonction lors de l’exécution et appeler une méthode sur ce type, sans savoir exactement ce que fait la méthode. Dans ce cas, vous pouvez utiliser une interface.

Donc, à la fin, vous n’obtenez rien de l’inheritance des classes statiques.

Ce que vous voulez réaliser en utilisant la hiérarchie de classes peut être atteint simplement par l’espace de noms. Ainsi, les langages qui prennent en charge les namespapces (comme C #) n’auront aucune implémentation de la hiérarchie des classes statiques. Comme vous ne pouvez instancier aucune des classes, vous avez uniquement besoin d’une organisation hiérarchique des définitions de classes que vous pouvez obtenir en utilisant des espaces de noms.

Vous pouvez utiliser la composition à la place … cela vous permettra d’accéder aux objects de classe à partir du type statique. Mais toujours pas implémenter des interfaces ou des classes abstraites

Bien que vous puissiez accéder aux membres statiques “hérités” via le nom des classes héritées, les membres statiques ne sont pas vraiment hérités. C’est en partie pourquoi ils ne peuvent pas être virtuels ou abstraits et ne peuvent pas être remplacés. Dans votre exemple, si vous avez déclaré Base.Method (), le compilateur mappera de toute façon un appel à Inherited.Method () à Base.Method (). Vous pourriez aussi bien appeler Base.Method () explicitement. Vous pouvez écrire un petit test et voir le résultat avec Reflector.

Donc, si vous ne pouvez pas hériter de membres statiques, et si les classes statiques ne peuvent contenir que des membres statiques, à quoi bon hériter une classe statique?

Hmmm … serait-ce différent si vous aviez juste des classes non statiques remplies de méthodes statiques ..?

Une solution de contournement que vous pouvez utiliser n’est pas d’utiliser des classes statiques mais de masquer le constructeur afin que les membres statiques des classes soient la seule chose accessible en dehors de la classe. Le résultat est une classe “statique” héritable essentiellement:

 public class TestClass { protected TestClass() { } public static T Add(T x, T y) { return (dynamic)x + (dynamic)y; } } public class TestClass : TestClass { // Inherited classes will also need to have protected constructors to prevent people from creating instances of them. protected TestClass() { } } TestClass.Add(3.0, 4.0) TestClass.Add(3, 4) // Creating a class instance is not allowed because the constructors are inaccessible. // new TestClass(); // new TestClass(); 

Malheureusement, à cause de la limitation du langage “par conception”, nous ne pouvons pas faire:

 public static class TestClass { public static T Add(T x, T y) { return (dynamic)x + (dynamic)y; } } public static class TestClass : TestClass { } 

Vous pouvez faire quelque chose qui ressemblera à un inheritance statique.

Voici l’astuce:

 public abstract class StaticBase where TSuccessor : StaticBase, new() { protected static readonly TSuccessor Instance = new TSuccessor(); } 

Ensuite, vous pouvez le faire:

 public class Base : StaticBase { public Base() { } public void MethodA() { } } public class Inherited : Base { private Inherited() { } public new static void MethodA() { Instance.MethodA(); } } 

La classe Inherited n’est pas elle-même statique, mais nous ne permettons pas de la créer. Il a en fait hérité du constructeur statique qui construit Base , ainsi que de toutes les propriétés et méthodes de Base disponibles en tant que statique. Il ne rest plus qu’à créer des wrappers statiques pour chaque méthode et propriété à exposer à votre contexte statique.

Il existe des inconvénients tels que la nécessité de créer manuellement des méthodes d’encapsulation statiques et un new mot-clé. Mais cette approche aide à prendre en charge quelque chose qui est vraiment similaire à l’inheritance statique.

PS Nous avons utilisé ceci pour créer des requêtes compilées, et cela peut en fait être remplacé par ConcurrentDictionary, mais un champ statique en lecture seule avec sa sécurité de thread était suffisant.

Les classes statiques et les membres de classe sont utilisés pour créer des données et des fonctions accessibles sans créer d’instance de la classe. Les membres de classe statiques peuvent être utilisés pour séparer des données et des comportements indépendants de toute identité d’object: les données et les fonctions ne changent pas indépendamment de ce qui arrive à l’object. Les classes statiques peuvent être utilisées lorsqu’il n’y a pas de données ou de comportement dans la classe qui dépendent de l’identité de l’object.

Une classe peut être déclarée statique, ce qui indique qu’elle ne contient que des membres statiques. Il est impossible d’utiliser le mot clé new pour créer des instances d’une classe statique. Les classes statiques sont chargées automatiquement par le Common Language Runtime (CLR) du .NET Framework lorsque le programme ou l’espace de noms contenant la classe est chargé.

Utilisez une classe statique pour contenir des méthodes qui ne sont pas associées à un object particulier. Par exemple, il est courant de créer un ensemble de méthodes qui n’agissent pas sur les données d’instance et qui ne sont pas associées à un object spécifique dans votre code. Vous pouvez utiliser une classe statique pour contenir ces méthodes.

Voici les principales caractéristiques d’une classe statique:

  1. Ils ne contiennent que des membres statiques.

  2. Ils ne peuvent pas être instanciés.

  3. Ils sont scellés.

  4. Ils ne peuvent pas contenir de constructeurs d’instance (Guide de programmation C #).

Créer une classe statique revient donc essentiellement à créer une classe contenant uniquement des membres statiques et un constructeur privé. Un constructeur privé empêche la classe d’être instanciée.

L’avantage d’utiliser une classe statique est que le compilateur peut vérifier qu’aucun membre de l’instance n’est ajouté accidentellement. Le compilateur garantira que des instances de cette classe ne peuvent pas être créées.

Les classes statiques sont scellées et ne peuvent donc pas être héritées. Ils ne peuvent hériter d’aucune classe sauf Object. Les classes statiques ne peuvent pas contenir de constructeur d’instance. Cependant, ils peuvent avoir un constructeur statique. Pour plus d’informations, voir Constructeurs statiques (Guide de programmation C #).

Lorsque nous créons une classe statique contenant uniquement les membres statiques et un constructeur privé. La seule raison est que le constructeur statique empêche l’instanciation de la classe pour que nous ne puissions pas hériter d’une classe statique. Le seul moyen d’accéder au membre du classe statique en utilisant le nom de la classe elle-même.Essayez d’hériter d’une classe statique n’est pas une bonne idée.