En réponse à cette question, le consensus général était que les méthodes statiques ne sont pas censées être remplacées (et donc les fonctions statiques en C # ne peuvent pas être virtuelles ou abstraites). Ce n'est pas seulement le cas en C #; Java l'interdit également et C ++ ne semble pas non plus l'aimer. Cependant, je peux penser à de nombreux exemples de fonctions statiques que je voudrais remplacer dans une classe enfant (par exemple, les méthodes d'usine). Bien qu'en théorie, il existe des moyens de les contourner, aucun d'entre eux n'est propre ou simple.
Pourquoi les fonctions statiques ne devraient-elles pas être remplaçables?
object-oriented-design
abstract-class
static-methods
PixelArtDragon
la source
la source
self
pointeur qui pointe vers la classe et non vers une instance de la classe.Réponses:
Avec les méthodes statiques, aucun objet ne permet de contrôler correctement le mécanisme de priorité.
Le mécanisme de méthode virtuelle de classe / instance normale permet un contrôle finement réglé des remplacements comme suit: chaque objet réel est une instance d'exactement une classe. Cette classe détermine le comportement des remplacements; il obtient toujours la première fissure aux méthodes virtuelles. Il peut alors choisir d'appeler la méthode parent au bon moment pour son implémentation. Chaque méthode parent obtient alors également son tour pour invoquer sa méthode parent. Il en résulte une belle cascade d'invocations parentales, qui accomplit l'une des notions de réutilisation de code pour lesquelles l'orientation d'objet est connue. (Ici, le code des classes de base / super est réutilisé d'une manière relativement complexe; une autre notion orthogonale de réutilisation de code dans OOP est simplement d'avoir plusieurs objets de la même classe.)
Les classes de base peuvent être réutilisées par diverses sous-classes, et chacune peut coexister confortablement. Chaque classe qui est utilisée pour instancier des objets dictant son propre comportement, coexistant pacifiquement et simultanément avec les autres. Le client a le contrôle sur les comportements qu'il souhaite et quand il choisit la classe à utiliser pour instancier un objet et le transmettre aux autres comme il le souhaite.
(Ce n'est pas un mécanisme parfait, car on peut toujours identifier les capacités qui ne sont pas prises en charge, bien sûr, c'est pourquoi des modèles comme la méthode d'usine et l'injection de dépendance sont superposés.)
Donc, si nous devions créer une capacité de substitution pour la statique sans rien changer d'autre, nous aurions du mal à ordonner les substitutions. Il serait difficile de définir un contexte limité pour l'applicabilité du remplacement, vous obtiendrez donc le remplacement globalement plutôt que localement comme avec les objets. Il n'y a aucun objet d'instance pour changer le comportement. Donc, si quelqu'un a invoqué la méthode statique qui a été remplacée par une autre classe, le remplacement doit-il prendre le contrôle ou non? S'il existe plusieurs remplacements de ce type, qui obtient le contrôle en premier? seconde? Avec les remplacements d'objet d'instance, ces questions ont toutes des réponses significatives et bien motivées, mais pas avec la statique.
Les remplacements pour la statique seraient considérablement chaotiques, et des choses comme cela ont déjà été faites.
Par exemple, Mac OS System 7 et versions antérieures utilisaient un mécanisme de correction de déroutement pour étendre le système en obtenant le contrôle des appels système effectués par l'application avant le système d'exploitation. Vous pouvez penser à la table de correctifs des appels système comme un tableau de pointeurs de fonction, un peu comme une table d'objets par exemple, sauf qu'il s'agissait d'une seule table globale.
Cela a causé un chagrin indescriptible aux programmeurs en raison de la nature non ordonnée de la correction des pièges. Quiconque a réussi à réparer le dernier piège a essentiellement gagné, même s'il ne le voulait pas. Chaque patcher du piège capturait la valeur de piège précédente pour une sorte de capacité d'appel parent, qui était extrêmement fragile. Suppression d'un correctif de déroutement, par exemple, lorsque vous n'avez plus besoin de connaître un appel système a été considéré comme une mauvaise forme car vous ne disposiez pas vraiment des informations nécessaires pour supprimer votre correctif (si vous le faisiez, vous décompacteriez également tout autre correctif qui aurait suivi. vous).
Cela ne veut pas dire qu'il serait impossible de créer un mécanisme pour les remplacements de statique, mais ce que je préférerais probablement faire à la place est de transformer les champs statiques et les méthodes statiques en champs d'instances et en méthodes d'instance de métaclasses, de sorte que l'objet normal des techniques d'orientation s'appliqueraient alors. Notez qu'il existe des systèmes qui le font également: CSE 341: classes et métaclasses Smalltalk ; Voir aussi: Quel est l'équivalent Smalltalk de la statique de Java?
J'essaie de dire que vous devrez faire une conception sérieuse des fonctionnalités du langage pour que cela fonctionne même raisonnablement bien. Par exemple, une approche naïve a été adoptée, a fait long feu, mais était très problématique, et sans doute (c'est-à-dire, je dirais) défectueuse sur le plan architectural en fournissant une abstraction incomplète et difficile à utiliser.
Au moment où vous avez terminé de concevoir la fonctionnalité de remplacement statique pour fonctionner correctement, vous venez peut-être d'inventer une forme de métaclasses, qui est une extension naturelle de la POO dans / pour les méthodes basées sur les classes. Il n'y a donc aucune raison de ne pas le faire - et certaines langues le font en fait. C'est peut-être un peu plus une exigence marginale qu'un certain nombre de langues choisissent de ne pas faire.
la source
this.instanceMethod()
a une résolution dynamique, donc siself.staticMethod()
a la même résolution, à savoir dynamique, ce ne serait plus une méthode statique.Le remplacement dépend de la répartition virtuelle: vous utilisez le type d'exécution du
this
paramètre pour décider de la méthode à appeler. Une méthode statique n'a pas dethis
paramètre, il n'y a donc rien à distribuer.Certains langages, notamment Delphi et Python, ont une portée "intermédiaire" qui permet cela: les méthodes de classe. Une méthode de classe n'est pas une méthode d'instance ordinaire, mais elle n'est pas statique non plus; il reçoit un
self
paramètre (de manière amusante, les deux langues appellent lethis
paramètreself
) qui est une référence au type d'objet lui-même, plutôt qu'à une instance de ce type. Avec cette valeur, vous disposez désormais d'un type pour effectuer une répartition virtuelle.Malheureusement, ni la JVM ni le CLR n'ont rien de comparable.
la source
self
ce sont les langages qui utilisent qui ont des classes comme objets réels et instanciés avec des méthodes redéfinissables - Smalltalk bien sûr, Ruby, Dart, Objective C, Self, Python? Par rapport aux langages qui prennent après C ++, où les classes ne sont pas des objets de première classe, même s'il y a un accès à la réflexion?virtual
puis remplacée dans une classe descendante, tout comme les méthodes d'instance.Tu demandes
je demande
Certaines langues vous obligent à démarrer le show de manière statique. Mais après cela, vous pouvez vraiment résoudre un grand nombre de problèmes sans aucune méthode statique.
Certaines personnes aiment utiliser des méthodes statiques chaque fois qu'il n'y a pas de dépendance à l'état dans un objet. Certaines personnes aiment utiliser des méthodes statiques pour la construction d'autres objets. Certaines personnes préfèrent éviter autant que possible les méthodes statiques.
Aucune de ces personnes n'a tort.
Si vous en avez besoin pour être remplaçable, arrêtez simplement de le qualifier de statique. Rien ne va se casser parce que vous avez un objet apatride qui vole autour.
la source
_start()
symbole sous Linux). Dans cet exemple, l'exécutable est l'objet (il a sa propre "table de répartition" et tout) et le point d'entrée est l'opération distribuée dynamiquement. Par conséquent, le point d'entrée d'un programme est intrinsèquement virtuel lorsqu'il est vu de l'extérieur et il peut facilement être rendu virtuel lorsqu'il est également vu de l'intérieur.Ce n'est pas une question de «devrait».
"Remplacement" signifie "répartition dynamique ". "Méthode statique" signifie "répartition statique". Si quelque chose est statique, il ne peut pas être remplacé. Si quelque chose peut être remplacé, ce n'est pas statique.
Votre question revient plutôt à demander: "Pourquoi les tricycles ne devraient-ils pas avoir quatre roues?" La définition de "tricycle" est celle qui a trois roues. Si c'est un tricycle, il ne peut pas avoir quatre roues, s'il a quatre roues, ce ne peut pas être un tricycle. De même, la définition de "méthode statique" est qu'elle est distribuée de manière statique. S'il s'agit d'une méthode statique, elle ne peut pas être distribuée dynamiquement, si elle peut être distribuée dynamiquement, elle ne peut pas être une méthode statique.
Il est bien sûr parfaitement possible d'avoir des méthodes de classe qui peuvent être surchargées. Ou, vous pourriez avoir un langage comme Ruby, où les classes sont des objets comme tout autre objet et peuvent donc avoir des méthodes d'instance, ce qui élimine complètement le besoin de méthodes de classe. (Ruby n'a qu'un seul type de méthodes: les méthodes d'instance. Il n'a pas de méthodes de classe, de méthodes statiques, de constructeurs, de fonctions ou de procédures.)
la source
En C #, vous appelez toujours des membres statiques en utilisant la classe, par exemple
BaseClass.StaticMethod()
, nonbaseObject.StaticMethod()
. Donc, finalement, si vous avezChildClass
hérité deBaseClass
etchildObject
une instance deChildClass
, vous ne pourrez pas appeler votre méthode statique à partir dechildObject
. Vous aurez toujours besoin d'utiliser explicitement la vraie classe, doncstatic virtual
ça n'a pas de sens.Ce que vous pouvez faire, c'est redéfinir la même
static
méthode dans votre classe enfant et utiliser lenew
mot - clé.S'il était possible d'appeler
baseObject.StaticMethod()
, votre question aurait du sens.la source