J'ai plusieurs classes qui n'ont pas vraiment besoin d'un état. Du point de vue organisationnel, je voudrais les hiérarchiser.
Mais il semble que je ne puisse pas déclarer d'héritage pour les classes statiques.
Quelque chose comme ca:
public static class Base
{
}
public static class Inherited : Base
{
}
ne fonctionnera pas.
Pourquoi les concepteurs de la langue ont-ils fermé cette possibilité?
c#
inheritance
static
Utilisateur
la source
la source
Réponses:
Citation d' ici :
Autres opinions de channel9
Et comme idée valable, littleguru a une "solution de contournement" partielle pour ce problème: le modèle Singleton .
la source
object
et tout le monde est censé le savoir. Les classes statiques héritent donc toujours deobject
, que vous le spécifiiez explicitement ou non.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 leur création).
Donc ça:
compile dans cet IL:
la source
Pensez-y de cette façon: vous accédez aux membres statiques via le nom du type, comme ceci:
Si vous héritiez de cette classe, vous devriez y accéder via le nouveau nom de type:
Ainsi, le nouvel élément n'a aucun rapport avec l'original lorsqu'il est utilisé dans le code. Il n'y aurait aucun moyen de profiter d'une relation d'héritage pour des choses comme le polymorphisme.
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 ajouter des méthodes à un type statique existant. Vous pouvez déjà le faire via des méthodes d'extension.
Peut-être voulez-vous pouvoir passer un statique
Type
à une fonction au moment 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 ne gagnez vraiment rien à hériter des classes statiques.
la source
SomeClass<T> where T:Foo
pourrait accéder aux membres deFoo
, et s'ilT
s'agissait d'une classe qui remplaçait certains membres statiques virtuels deFoo
, la classe générique utiliserait ces remplacements. Il serait probablement même possible de définir une convention par laquelle les langues pourraient le faire d'une manière compatible avec le CLR actuel (par exemple, une classe avec de tels membres devrait définir une classe non statique protégée qui contient de tels membres d'instance, avec un champ statique contenant une instance de ce type).Ce que vous voulez réaliser en utilisant la hiérarchie des classes peut être réalisé simplement par le biais de l'espace de noms. Ainsi, les langages qui prennent en charge les espaces de noms (comme C #) n'auront aucune utilité d'implémenter la hiérarchie des classes de classes statiques. Comme vous ne pouvez instancier aucune des classes, tout ce dont vous avez besoin est une organisation hiérarchique des définitions de classe que vous pouvez obtenir en utilisant des espaces de noms
la source
Vous pouvez utiliser la composition à la place ... cela vous permettra d'accéder aux objets de classe à partir du type statique. Mais je ne peux toujours pas implémenter des interfaces ou des classes abstraites
la source
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é un Base.Method (), le compilateur mappera de toute façon un appel à Inherited.Method () à Base.Method (). Vous pourriez aussi bien appeler explicitement Base.Method (). 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 d'une classe statique?
la source
Hmmm ... serait-ce bien différent si vous aviez juste des classes non statiques remplies de méthodes statiques ..?
la source
Une solution de contournement que vous pouvez faire 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:
Malheureusement, en raison de la limitation du langage "par conception", nous ne pouvons pas faire:
la source
Vous pouvez faire quelque chose qui ressemblera à un héritage statique.
Voici l'astuce:
Ensuite, vous pouvez le faire:
La
Inherited
classe n'est pas statique elle-même, mais nous ne permettons pas de la créer. Il a en fait hérité du constructeur statique qui construitBase
et de toutes les propriétés et méthodesBase
disponibles en tant que statique. Maintenant, il ne reste plus qu'à créer des wrappers statiques pour chaque méthode et propriété que vous devez exposer à votre contexte statique.Il y a des inconvénients comme la nécessité de créer manuellement des méthodes et des
new
mots clés d' encapsuleurs statiques . Mais cette approche permet de prendre en charge quelque chose qui est vraiment similaire à l'héritage statique.PS Nous l'avons utilisé 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 assez bon.
la source
Ma réponse: mauvais choix de conception. ;-)
Il s'agit d'un débat intéressant axé sur l'impact syntaxique. À mon avis, l'essentiel de l'argument est qu'une décision de conception a conduit à des classes statiques scellées. Un accent sur la transparence des noms de classe statiques apparaissant au niveau supérieur au lieu de se cacher («confus») derrière les noms d'enfants? On peut imaginer une implémentation de langage qui pourrait accéder directement à la base ou à l'enfant, déroutant.
Un pseudo exemple, en supposant que l'héritage statique a été défini d'une manière ou d'une autre.
conduirait à:
qui pourrait (aurait?) un impact sur le même stockage que
Très perturbant!
Mais attendez! Comment le compilateur gérerait-il MyStaticBase et MyStaticChild ayant la même signature définie dans les deux? Si l'enfant remplace ce que mon exemple ci-dessus ne changerait PAS le même stockage, peut-être? Cela conduit à encore plus de confusion.
Je crois qu'il existe une forte justification de l'espace informationnel pour un héritage statique limité. Plus sur les limites sous peu. Ce pseudocode montre la valeur:
Vous obtenez alors:
L'utilisation ressemble à:
La personne qui crée l'enfant statique n'a pas besoin de penser au processus de sérialisation tant qu'elle comprend les limitations qui pourraient être placées sur le moteur de sérialisation de la plateforme ou de l'environnement.
La statique (singletons et autres formes de «globaux») survient souvent autour du stockage de la configuration. L'héritage statique permettrait à ce type d'allocation de responsabilité d'être clairement représenté dans la syntaxe pour correspondre à une hiérarchie de configurations. Bien que, comme je l'ai montré, il existe de nombreuses possibilités d'ambiguïté massive si des concepts de base d'héritage statique sont mis en œuvre.
Je crois que le bon choix de conception serait de permettre l'héritage statique avec des limitations spécifiques:
Vous pouvez toujours changer le même magasin via une référence générique
MyStaticBase<ChildPayload>.SomeBaseField
. Mais vous seriez découragé car le type générique devrait être spécifié. Alors que la référence de l' enfant serait plus propre:MyStaticChild.SomeBaseField
.Je ne suis pas un écrivain de compilateur, donc je ne sais pas si je manque quelque chose sur les difficultés de mise en œuvre de ces limitations dans un compilateur. Cela dit, je crois fermement qu'il existe un besoin d'espace informationnel pour un héritage statique limité et la réponse de base est que vous ne pouvez pas en raison d'un choix de conception médiocre (ou trop simple).
la source
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 les données et les comportements qui sont indépendants de toute identité d'objet: les données et les fonctions ne changent pas quoi qu'il arrive à l'objet. Les classes statiques peuvent être utilisées lorsqu'il n'y a pas de données ou de comportement dans la classe qui dépend de l'identité de l'objet.
Une classe peut être déclarée statique, ce qui indique qu'elle ne contient que des membres statiques. Il n'est pas possible d'utiliser le nouveau mot clé pour créer des instances d'une classe statique. Les classes statiques sont chargées automatiquement par le Common Language Runtime (CLR) .NET Framework lorsque le programme ou l'espace de noms qui contient la classe est chargé.
Utilisez une classe statique pour contenir des méthodes qui ne sont pas associées à un objet 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 ne sont pas associées à un objet spécifique dans votre code. Vous pouvez utiliser une classe statique pour conserver ces méthodes.
Voici les principales caractéristiques d'une classe statique:
Ils ne contiennent que des membres statiques.
Ils ne peuvent pas être instanciés.
Ils sont scellés.
Ils ne peuvent pas contenir de constructeurs d'instance (Guide de programmation C #).
La création d'une classe statique est donc fondamentalement la même chose que la création d'une classe qui ne contient que 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 pour s'assurer qu'aucun membre d'instance n'est ajouté accidentellement. Le compilateur garantit que les 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, consultez Constructeurs statiques (Guide de programmation C #).
la source
Lorsque nous créons une classe statique qui ne contient que les membres statiques et un constructeur privé. La seule raison est que le constructeur statique empêche la classe d'être instanciée pour cela, nous ne pouvons pas hériter d'une classe statique. La seule façon d'accéder au membre du classe statique en utilisant le nom de classe lui-même.Essayer d'hériter d'une classe statique n'est pas une bonne idée.
la source