Pourquoi rendre certaines méthodes pour les types de données statiques ?

Aug 15 2020

En C #, par exemple, il existe des méthodes statiques pour dire si une chaîne est null ou vide , trouver un élément dans un tableau, effacer un tableau, etc. Cependant, il existe une méthode d'instance pour remplacer les caractères dans une chaîne, et à la fois statique et instance méthodes de copie d'éléments entre tableaux.

De même, en Python, il existe des fonctions pour obtenir la longueur d'une liste, pour filtrer une liste, etc., mais des méthodes d'instance pour trouver l'index d'un élément et pour copier la liste.

Au contraire, en JavaScript, pratiquement toutes les opérations que je dois effectuer sur un type de données intégré seront accessibles via une méthode ou une propriété d'instance.

Alors, quelle est la raison de rendre certaines choses statiques et d'autres non ?

EDIT : Pour être clair, je comprends le but des méthodes statiques. Ma question porte davantage sur la raison pour laquelle certaines méthodes sont écrites comme statiques alors qu'elles auraient pu être écrites comme des méthodes d'instance. Comme Findpour les tableaux et Formatpour les chaînes en C#, et filteret lenen Python.

Réponses

2 AvnerShahar-Kashtan Aug 15 2020 at 15:09

EDIT : la question a été affinée, je vais donc affiner ma réponse, mais laissez la précédente ci-dessous afin de ne pas rendre les commentaires non pertinents.

Il peut y avoir plusieurs raisons d'implémenter une méthode en tant que méthode statique au lieu d'une méthode d'instance, avec différents langages ou frameworks ayant éventuellement des justifications différentes :

  1. L'interface publique d'un objet est un contrat. Si votre Arraytype expose une Sortméthode, chaque tableau à partir de maintenant, quel que soit le type ou la version du langage, doit la prendre en charge. Si, toutefois, an Arrayn'est qu'une représentation de données en mémoire avec un contrat léger et que la logique est déplacée vers une classe telle que Array.Sort, cela vous donne plus de flexibilité pour étendre ou modifier votre comportement sans rompre la compatibilité.

  2. Voir cette citation du Clean Code de Bob Martin :

Les objets exposent le comportement et cachent les données ; La structure des données expose les données et n'a pas de comportement significatif"

Dans ce cas, la Listclasse est une classe qui expose le comportement - elle cache ses données (elle est implémentée comme un tableau redimensionnable, mais c'est un détail d'implémentation), mais expose les fonctionnalités. Un int[], cependant, est une structure de données. intC'est un bloc alloué séquentiellement . Il a une Lengthpropriété car il fait partie de ses données , mais n'a pas beaucoup de comportement - le comportement est transféré à une classe qui opère dessus.

  1. C'est peut-être un choix stylistique. Python n'est pas un langage purement OO et peut ne pas avoir la garantie Java/C # "tout est un objet", il a donc choisi d'utiliser des fonctions de langage comme len()celles-ci pouvant être utilisées, que son paramètre soit une instance d'objet ou non.

Réponse précédente

La raison d'être des méthodes statiques en C# est d'avoir des méthodes qui sont liées à un type mais pas à une instance . Il peut y avoir plusieurs raisons à cela :

  1. Les méthodes qui peuvent fonctionner à la fois sur une instance et null, comme string.IsNullOrEmpty, ne peuvent naturellement pas être des méthodes d'instance - car il se peut qu'il n'y ait pas d'instance.
  2. De même, les méthodes de fabrique qui créent une instance n'ont pas d'instance à partir de laquelle elles peuvent être appelées. Par exemple, la méthode statique obsolète de quelqu'un WebRequest.Create()renvoie une nouvelle instance d'un type dérivé de WebRequest.
  3. Bien qu'il soit facile d'oublier, .NET a une gestion différente pour un type intégral natif ( int i =5) et un type de référence encadré autour de lui ( object boxed = 5). Si vous appelez une méthode sur un type valeur ( int i = 5; t.ToString();), vous encourez un coût de mise en boîte. C'est pourquoi certaines opérations ne sont pas définies comme une méthode sur un objet, mais comme une méthode statique qui accepte une valeur. C'est pourquoi les opérations mathématiques telles que Math.Absne sont pas définies comme des méthodes sur les types encadrés, mais comme des fonctions statiques qui reçoivent et renvoient des valeurs.
  4. Parfois, des méthodes statiques sont utilisées pour "configurer" un type, pas une instance spécifique mais le comportement de ce type dans le système. Par exemple, [ServicePointManager.SetTcpKeepAlive()][1]configure le comportement de toutes les classes qui utilisent la pile HTTP(s) partagée dans .NET, afin que vous puissiez toutes les configurer via ces méthodes statiques.
5 amon Aug 15 2020 at 15:28

Les méthodes statiques ont beaucoup de sens

  • lorsque la méthode est liée au type mais ne nécessite pas d'instance existante ; ou
  • lorsque le langage prend en charge l'espace de noms uniquement via des classes.

C# ne prend en charge que les fonctions en tant que membres de classes, de sorte que les fonctions d'assistance doivent être écrites en tant que méthodes statiques. La classe C# Mathen est un excellent exemple.

JavaScript n'a pas de classes, mais chaque variable non locale est associée à un objet - dans le navigateur, la plupart des API sont accessibles via l' windowobjet. Cependant, certaines méthodes sont accessibles via un objet de type classe, par exemple Array.isArray(x).

Python a une conception idiosyncrasique qui est principalement orientée objet, mais possède certaines fonctions intégrées comme len()ou iter(), en grande partie pour des raisons historiques. Sous le capot, ils invoquent des méthodes réelles, par exemple iter(x)est généralement x.__iter__(), avec une solution de repli pour les objets qui peuvent être indexés comme une liste.

Plus intéressantes sont les méthodes qui ne sont staticpas dues aux bizarreries du langage, mais parce que cela a du sens. Les méthodes de type constructeur ou de type usine sont l'exemple classique où nous n'avons pas d'objet existant sur lequel nous pourrions appeler une méthode. Certaines fonctions n'opèrent pas non plus sur exactement un objet, par exemple String.IsNullOrEmpty(x)opèrent sur zéro ou un objet. Cela ne fonctionne pas comme une méthode, par exemple x.IsNullOrEmpty()lèverait une exception si elle est nulle ! La Array.isArray(x)méthode en JS est un autre excellent exemple : nous voulons appeler isArray(x)des objets de n'importe quel type, pas seulement des tableaux. Ainsi, une méthode d'instance ne fonctionne que si elle fait partie du prototype de chaque objet.