Quelle est la différence entre les deux méthodes UpdateSubject ci-dessous? Je me suis senti mieux d'utiliser des méthodes statiques si vous voulez simplement opérer sur les entités. Dans quelles situations dois-je aller avec des méthodes non statiques?
public class Subject
{
public int Id {get; set;}
public string Name { get; set; }
public static bool UpdateSubject(Subject subject)
{
//Do something and return result
return true;
}
public bool UpdateSubject()
{
//Do something on 'this' and return result
return true;
}
}
Je sais que la communauté suscitera de nombreux éloges pour cette question vraiment agaçante, mais je ne pouvais pas m'empêcher de la poser.
Est-ce que cela devient impraticable en matière d'héritage?
Mise à jour:
Cela se passe sur notre lieu de travail maintenant. Nous travaillons sur une application Web asp.net de 6 mois avec 5 développeurs. Notre architecte a décidé d'utiliser toutes les méthodes statiques pour toutes les API. Son raisonnement étant que les méthodes statiques sont légères et qu'il profite aux applications Web en réduisant la charge du serveur.
la source
Réponses:
Je vais aller avec les problèmes les plus évidents de méthodes statiques avec des paramètres explicites "this":
Vous perdez la répartition virtuelle et par la suite le polymorphisme. Vous ne pouvez jamais remplacer cette méthode dans une classe dérivée. Bien sûr, vous pouvez déclarer une méthode
new
(static
) dans une classe dérivée, mais tout code y accédant doit connaître la hiérarchie entière de la classe et procéder à une vérification et à une conversion explicites, ce qui est précisément ce que OO est censé éviter .Sorte d'une extension de # 1, vous ne pouvez pas remplacer les instances de la classe par une interface , car les interfaces (dans la plupart des langues) ne peuvent pas déclarer de
static
méthodes.La verbosité inutile. Lequel est le plus lisible:
Subject.Update(subject)
ou justesubject.Update()
?Vérification d'argument. Là encore, cela dépend de la langue, mais beaucoup compileront une vérification implicite pour s’assurer que l’
this
argument n’est pasnull
utilisé pour empêcher un bogue de référence null de créer des conditions d’exécution non sûres (sorte de dépassement de mémoire tampon). N'utilisant pas de méthodes d'instance, vous devez ajouter cette vérification explicitement au début de chaque méthode.C'est confu. Quand un programmeur normal et raisonnable voit une
static
méthode, il va naturellement supposer qu’elle n’exige pas d’instance valide (à moins qu’elle prenne plusieurs instances, comme une méthode de comparaison ou d’égalité, ou puisse fonctionner sur desnull
références). . Voir les méthodes statiques utilisées de cette façon va nous faire faire une double ou peut-être une triple prise, et après la 4ème ou 5ème fois, nous allons être stressés et en colère et dieu vous aidera si nous connaissons votre adresse personnelle.C'est une forme de duplication. En réalité, lorsque vous appelez une méthode d'instance, le compilateur ou le moteur d'exécution la recherche dans la table de méthodes du type et l'invoque
this
sous forme d'argument. Vous ré-implémentez ce que le compilateur fait déjà. Vous violez DRY , répétez le même paramètre encore et encore selon différentes méthodes lorsque vous n'en avez pas besoin.Il est difficile de concevoir une bonne raison de remplacer les méthodes d'instance par des méthodes statiques. S'il vous plaît ne pas.
la source
File
,FileInfo
etDirectoryInfo
(et en fait, il y a des bibliothèques qui les cachent derrière des interfaces qui peuvent être injectés au besoin et raillé dans les tests).Vous avez à peu près décrit exactement comment vous faites la POO en C, dans lequel seules les méthodes statiques sont disponibles, et "this" est un pointeur struct. Et oui, vous pouvez effectuer un polymorphisme d’exécution en C en spécifiant qu’un pointeur de fonction pendant la construction doit être stocké en tant qu’un des éléments de la structure. Les méthodes d'instance disponibles dans d'autres langues ne sont que des sucres syntaxiques qui font essentiellement la même chose sous le capot. Certaines langues, comme python, sont à mi-chemin, le paramètre "self" est explicitement répertorié, mais une syntaxe spéciale pour l'appeler gère l'héritage et le polymorphisme pour vous.
la source
obj->type->mthd(obj, ...);
et cela est sensiblement similaire à ce qui se produit avec l’envoi virtuel dans d’autres langues (mais en coulisse).Le problème avec la méthode statique vient au moment où vous avez besoin d'une sous-classe.
Les méthodes statiques ne peuvent pas être remplacées dans les sous-classes. Par conséquent, vos nouvelles classes ne peuvent pas fournir de nouvelles implémentations des méthodes, ce qui les rend moins utiles.
la source
Si vous déclarez une méthode
static
, vous n'avez pas besoin d'instancier un objet de la classe (à l'aide dunew
mot clé) pour exécuter la méthode. Toutefois, vous ne pouvez faire référence à aucune variable membre, sauf si elles sont également statiques. Dans ce cas, ces variables membres appartiennent à la classe et non à un objet instancié spécifique de la classe.En d'autres termes, le
static
mot - clé fait en sorte qu'une déclaration fasse partie de la définition de la classe. Ainsi, elle devient un point de référence unique pour toutes les occurrences de la classe (objets instanciés à partir de la classe).Il s’ensuit que si vous souhaitez que plusieurs copies en cours d’exécution de votre classe ne soient pas partagées entre toutes vos copies en cours d’exécution (c’est-à-dire que chaque objet possède son propre état unique), ne peut pas déclarer ces variables membres statiques.
En général, vous ne devez utiliser des
static
classes et des méthodes que lorsque vous créez des méthodes utilitaires acceptant un ou plusieurs paramètres et renvoyant un objet de quelque sorte que ce soit, sans aucun effet secondaire (par exemple, modification des variables d'état dans la classe).la source
static
signifie, il demande pourquoi ne pas tout déclarer comme statique.Subject
- mais comme un paramètre explicite, au lieu de l'implicitethis
paramètre.this
paramètre implicite . Il existe des différences dans les attentes, mais en dehors de l'héritage, il n'y a pas de réelle différence dans ce que vous pouvez faire. Par exemple, vous pouvez accéder à ces membres non statiques via le paramètre explicit.La raison pour laquelle les gens soutiennent que "les méthodes statiques montrent une mauvaise conception" n'est pas nécessairement due aux méthodes, mais bien à des données statiques, implicites ou explicites. Par implicite, je veux dire TOUT état dans le programme qui n'est pas contenu dans les valeurs de retour ou les paramètres. La modification d'état dans une fonction statique est un retour à la programmation procédurale. Toutefois, si la fonction ne modifie pas l'état ou ne délègue pas la modification d'état aux fonctions d'objet composant, il s'agit en réalité d'un paradigme fonctionnel plutôt que procédural.
Si vous ne changez pas d'état, les méthodes et les classes statiques peuvent présenter de nombreux avantages. Il est beaucoup plus facile de s’assurer que la méthode est pure, et donc exempte d’effets secondaires et que les erreurs éventuelles sont entièrement reproductibles. Cela garantit également que différentes méthodes utilisant plusieurs bibliothèques utilisant une bibliothèque partagée peuvent être assurées qu'elles obtiendront les mêmes résultats avec la même entrée, ce qui facilite beaucoup le suivi des erreurs et les tests unitaires.
En fin de compte, il n'y a pas de différence de pratique entre les objets surdimensionnés couramment vus tels que 'StateManager' et les données statiques ou globales. L'avantage des méthodes statiques utilisées correctement est qu'elles peuvent indiquer l'intention de l'auteur de ne pas modifier l'état à des réviseurs ultérieurs.
la source
making ... unit testing much easier.
Non ça ne va pas. Il fait fait tout code qui appelle des méthodes statiques impossible à l' unité test, puisque vous ne pouvez pas l' isoler de la méthode statique. Un appel à une méthode statique devient une dépendance codée en dur à cette classe.Selon la langue et ce que vous essayez de faire, la réponse peut être qu'il n'y a pas beaucoup de différence, mais la
static
version est un peu plus encombrée.Comme votre exemple de syntaxe le suggère en Java ou en C #, je pense que Thorbjørn Ravn Andersen a raison de signaler le problème fondamental (avec la liaison tardive). Avec une méthode statique, il n'y a pas de paramètre "spécial" sur lequel une liaison tardive doit être basée, vous ne pouvez donc pas avoir de liaison tardive.
En effet, une méthode statique est simplement une fonction dans un module, ce module ayant le même nom que la classe - il ne s'agit pas vraiment d'une méthode de POO.
la source
Vous êtes en train de vaincre la totalité des objets lorsque vous faites cela. Il y a une bonne raison pour laquelle nous avons quasiment changé de code de procédure au code orienté objet.
Je ne déclarerais JAMAIS une méthode statique prenant le type de classe en tant que paramètre. Cela rend le code plus complexe sans aucun gain.
la source
object
à unestatic
méthode et retourniez une nouvelleobject
. Les programmeurs fonctionnels le font tout le temps.Math
classe statique "complexe sans gain" ou préférez-vous que tous les types de nombres aient des méthodes virtuelles définissant la valeur absolue, la négation, l'ajout, la quadrature, les racines arbitraires, etc.? Je ne pense pas. les objets sont propres lorsque vous devez stocker un état mutable masqué où vous devez appliquer des invariants. en mélangeant chaque méthode concievable qui opère sur un type dans le type lui-même, c’est quelque chose qui conduit à un code complexe et non maintenable. Je suis d'accord avec Robert, vous voudrez peut-être regarder comment fonctionnent les programmeurs, cela peut être une véritable révélation!Il y a beaucoup de bonnes réponses ici, et elles sont beaucoup plus perspicaces et mieux informées que tout ce que je pourrais jamais trouver comme réponse, mais je sens qu'il y a un petit quelque chose qui n'est pas abordé:
"Notre architecte a décidé que nous utilisions toutes les méthodes statiques pour toutes les API. Son raisonnement étant léger, il favorise les applications Web en réduisant la charge du serveur ."
(l'accent gras est le mien)
Mon 2c sur cette partie de la question est la suivante:
Théoriquement, ce qui est dit là est vrai: l'appel d'une méthode statique n'engendre que la surcharge de cette méthode. L'appel d'une méthode non statique (instance) entraîne la surcharge supplémentaire liée à l'instanciation initiale de l'objet et, à un moment donné, à la destruction de l'instance (manuellement ou via un certain type de garbage collection automatique, en fonction de la plate-forme utilisée).
La pièce un peu de l'avocat du diable à ce sujet: nous pouvons aller encore plus loin et dire des choses telles que:
cela peut devenir très grave si une instance est créée pour chaque invocation de la méthode (instance) (au lieu de simplement la laisser statique et de l'appeler ainsi)
En fonction de la complexité du constructeur, du type hyerarchy, des autres membres de l'instance et d'autres facteurs inconnus, la surcharge supplémentaire liée à l'appel d'une méthode non statique peut varier et devenir très importante.
En vérité, à mon humble avis, les points ci-dessus (et l'approche générale consistant à "utilisons la statique parce qu'ils sont plus rapides") sont des arguments / évaluations de l'homme de paille:
si le code est bon et, plus spécifique à cet argument, si les instances ne sont créées que lorsque cela est nécessaire (et détruites de manière optimale), vous n’obtenez pas de surcharge supplémentaire lorsque vous utilisez des méthodes d’insance lorsque cela est approprié (parce que si ne crée que les objets nécessaires, ceux-ci auraient été créés même si cette méthode avait été déclarée statique quelque part où = surcharge du même instanciation)
en abusant de cette façon de la déclaration statique des méthodes, il est possible de masquer certains problèmes liés à la manière dont les instances sont créées (étant donné que la méthode est statique, un code d’instanciation incorrect risque de passer inaperçu plus tard, et ce n’est jamais bon).
la source
C'est une question très intéressante qui a tendance à avoir des réponses très différentes selon la communauté à laquelle vous le posez. D'autres réponses semblent être le biais C # ou Java: un langage de programmation (principalement) orienté objet pur et ayant une sorte de vue idiomatique de ce qu'est l'orientation objet.
Dans d'autres communautés, telles que C ++, l'orientation des objets est interprétée avec plus de libéralité. Certains experts bien connus ont étudié le sujet et, en fait, concluent que les fonctions libres améliorent l’encapsulation (c’est le mien).
Pour ceux qui ne connaissent pas la terminologie C ++:
Maintenant, pour répondre à votre question:
Non, vous ne devriez pas toujours utiliser des méthodes statiques.
Cependant, vous devez les utiliser chaque fois que vous devez uniquement utiliser l' API publique d'une classe.
la source
en Java ...
Les méthodes statiques ne sont pas écrasées, mais cachées. Ce serait une grosse différence (problème?) Dans le cas de l'extension de la classe.
D'autre part, j'ai remarqué que les programmeurs Java ont tendance à penser que tout DOIT être objet, sans vraiment comprendre pourquoi, et je ne suis pas d'accord.
Static doit être utilisé pour le code spécifique à la classe. La statique ne fonctionne pas bien avec l'héritage.
Quelques bons exemples d'utilisation de méthodes statiques sont des fonctions indépendantes sans effets secondaires.
voir aussi le mot clé synchronisé ...
la source