PHP est mon premier langage de programmation. Je ne peux pas vraiment comprendre quand utiliser des classes statiques ou des objets instanciés.
Je réalise que vous pouvez dupliquer et cloner des objets. Cependant, pendant tout mon temps en utilisant php, tout objet ou fonction se terminait toujours par une valeur de retour unique (tableau, chaîne, int) ou void.
Je comprends les concepts des livres comme une classe de personnages de jeux vidéo. dupliquez l'objet voiture et rendez le nouveau rouge , cela a du sens, mais ce qui ne l'est pas, c'est son application dans les applications PHP et Web.
Un exemple simple. Un blog. Quels objets d'un blog seraient mieux implémentés en tant qu'objets statiques ou instanciés? La classe DB? Pourquoi ne pas simplement instancier l'objet db dans la portée globale? Pourquoi ne pas rendre chaque objet statique à la place? Et les performances?
Est-ce juste du style? Y a-t-il une bonne façon de faire ça?
Les deux principales raisons contre l'utilisation de méthodes statiques sont:
Avoir un appel de méthode statique dans une autre méthode est en fait pire que d'importer une variable globale. En PHP, les classes sont des symboles globaux, donc chaque fois que vous appelez une méthode statique, vous vous fiez à un symbole global (le nom de la classe). C'est un cas où le global est mauvais. J'ai eu des problèmes avec ce type d'approche avec certains composants de Zend Framework. Il existe des classes qui utilisent des appels de méthodes statiques (usines) pour créer des objets. Il était impossible pour moi de fournir une autre usine à cette instance afin de récupérer un objet personnalisé. La solution à ce problème consiste à n'utiliser que des instances et des méthodes instace et à appliquer des singletons et autres au début du programme.
Miško Hevery , qui travaille en tant que coach agile chez Google, a une théorie intéressante, ou plutôt conseille, que nous devrions séparer le temps de création de l'objet du moment où nous utilisons l'objet. Le cycle de vie d'un programme est donc divisé en deux. La première partie (
main()
disons la méthode), qui prend en charge tout le câblage des objets dans votre application et la partie qui fait le travail réel.Donc au lieu d'avoir:
Nous devrions plutôt faire:
Et puis, dans l'index / page principale, nous ferions (c'est l'étape de câblage de l'objet, ou le temps de créer le graphique des instances à utiliser par le programme):
L'idée principale est de découpler les dépendances de vos classes. De cette façon, le code est beaucoup plus extensible et, la partie la plus importante pour moi, testable. Pourquoi est-il plus important d'être testable? Parce que je n'écris pas toujours de code de bibliothèque, l'extensibilité n'est donc pas si importante, mais la testabilité est importante lorsque je refactore. Quoi qu'il en soit, le code testable produit généralement du code extensible, donc ce n'est pas vraiment une situation de l'un ou l'autre.
Miško Hevery fait également une distinction claire entre les singletons et les singletons (avec ou sans un S majuscule). La différence est très simple. Les singletons avec un "s" minuscule sont imposés par le câblage dans l'index / main. Vous instanciez un objet d'une classe qui n'implémente pas le modèle Singleton et veillez à ne transmettre cette instance qu'à toute autre instance qui en a besoin. D'autre part, Singleton, avec un «S» majuscule, est une implémentation du modèle classique (anti-). Fondamentalement, un global déguisé qui n'a pas beaucoup d'utilité dans le monde PHP. Je n'en ai pas vu jusqu'à présent. Si vous voulez qu'une seule connexion DB soit utilisée par toutes vos classes, il est préférable de le faire comme ceci:
En faisant ce qui précède, il est clair que nous avons un singleton et nous avons également un bon moyen d'injecter un faux ou un stub dans nos tests. C'est étonnamment comment les tests unitaires conduisent à une meilleure conception. Mais cela a beaucoup de sens quand vous pensez que les tests vous obligent à réfléchir à la façon dont vous utiliseriez ce code.
La seule situation où j'utiliserais (et je les ai utilisés pour imiter l'objet prototype JavaScript dans PHP 5.3) des membres statiques est lorsque je sais que le champ respectif aura la même valeur cross-instance. À ce stade, vous pouvez utiliser une propriété statique et peut-être une paire de méthodes getter / setter statiques. Quoi qu'il en soit, n'oubliez pas d'ajouter la possibilité de remplacer le membre statique par un membre d'instance. Par exemple, Zend Framework utilisait une propriété statique afin de spécifier le nom de la classe d'adaptateur de base de données utilisée dans les instances de
Zend_Db_Table
. Cela fait un moment que je ne les ai pas utilisés, donc ce n'est peut-être plus pertinent, mais c'est comme ça que je m'en souviens.Les méthodes statiques qui ne traitent pas des propriétés statiques devraient être des fonctions. PHP a des fonctions et nous devrions les utiliser.
la source
Ainsi, en PHP, la statique peut être appliquée aux fonctions ou aux variables. Les variables non statiques sont liées à une instance spécifique d'une classe. Les méthodes non statiques agissent sur une instance d'une classe. Alors inventons une classe appelée
BlogPost
.title
serait un membre non statique. Il contient le titre de cet article de blog. Nous pourrions également avoir une méthode appeléefind_related()
. Ce n'est pas statique, car il nécessite des informations provenant d'une instance spécifique de la classe de publication de blog.Cette classe ressemblerait à quelque chose comme ceci:
D'un autre côté, en utilisant des fonctions statiques, vous pouvez écrire une classe comme celle-ci:
Dans ce cas, puisque la fonction est statique et n'agit sur aucun article de blog en particulier, vous devez passer l'article de blog en tant qu'argument.
Fondamentalement, c'est une question sur la conception orientée objet. Vos classes sont les noms de votre système et les fonctions qui agissent sur elles sont les verbes. Les fonctions statiques sont procédurales. Vous passez l'objet des fonctions comme arguments.
Mise à jour: j'ajouterais également que la décision se situe rarement entre les méthodes d'instance et les méthodes statiques, et plus entre l'utilisation de classes et l'utilisation de tableaux associatifs. Par exemple, dans une application de blog, vous lisez des articles de blog à partir de la base de données et les convertissez en objets, ou vous les laissez dans le jeu de résultats et les traitez comme des tableaux associatifs. Ensuite, vous écrivez des fonctions qui prennent des tableaux associatifs ou des listes de tableaux associatifs comme arguments.
Dans le scénario OO, vous écrivez des méthodes sur votre
BlogPost
classe qui agissent sur des publications individuelles, et vous écrivez des méthodes statiques qui agissent sur des collections de publications.la source
Un long chemin, oui. Vous pouvez écrire des programmes orientés objet parfaitement bons sans jamais utiliser de membres statiques. En fait, certaines personnes diraient que les membres statiques sont en premier lieu une impureté. Je suggérerais que - en tant que débutant en oop - vous essayez d'éviter les membres statiques tous ensemble. Cela vous forcera à écrire dans un style orienté objet plutôt que procédural .
la source
J'ai une approche différente de la plupart des réponses ici, en particulier lors de l'utilisation de PHP. Je pense que toutes les classes devraient être statiques à moins que vous n'ayez une bonne raison de ne pas le faire. Certaines des raisons «pourquoi pas» sont:
Permettez-moi de prendre un exemple. Puisque chaque script PHP produit du code HTML, mon framework a une classe d'écrivain html. Cela garantit qu'aucune autre classe ne tentera d'écrire du HTML car il s'agit d'une tâche spécialisée qui doit être concentrée dans une seule classe.
En règle générale, vous utiliseriez la classe html comme ceci:
Chaque fois que get_buffer () est appelé, il réinitialise tout pour que la classe suivante à utiliser l'écrivain html démarre dans un état connu.
Toutes mes classes statiques ont une fonction init () qui doit être appelée avant que la classe ne soit utilisée pour la première fois. C'est plus par convention qu'une nécessité.
L'alternative à une classe statique dans ce cas est compliquée. Vous ne voudriez pas que chaque classe qui a besoin d'écrire un tout petit peu de html doive gérer une instance de l'écrivain html.
Maintenant, je vais vous donner un exemple de ne pas utiliser de classes statiques. Ma classe de formulaire gère une liste d'éléments de formulaire tels que les entrées de texte, les listes déroulantes, etc. Il est généralement utilisé comme ceci:
Il n'y a aucun moyen de faire cela avec des classes statiques, d'autant plus que certains des constructeurs de chaque classe ajoutée font beaucoup de travail. De plus, la chaîne d'héritage pour tous les éléments est assez complexe. C'est donc un exemple clair où les classes statiques ne doivent pas être utilisées.
La plupart des classes utilitaires telles que celles convertissant / formatant des chaînes sont de bons candidats pour être une classe statique. Ma règle est simple: tout devient statique en PHP à moins qu'il n'y ait une raison pour laquelle cela ne devrait pas.
la source
"Avoir un appel de méthode statique dans une autre méthode est en fait pire que d'importer une variable globale." (définir "pire") ... et "Les méthodes statiques qui ne traitent pas de propriétés statiques devraient être des fonctions".
Ce sont deux déclarations assez radicales. Si j'ai un ensemble de fonctions qui sont liées dans le sujet, mais que les données d'instance sont totalement inappropriées, je préférerais de loin les avoir définies dans une classe et non chacune d'elles dans l'espace de noms global. J'utilise juste les mécanismes disponibles dans PHP5 pour
c'est tout simplement un moyen pratique d'imposer une cohésion plus élevée et un couplage plus faible.
Et FWIW - il n'y a pas une telle chose, au moins en PHP5, comme "classes statiques"; les méthodes et les propriétés peuvent être statiques. Pour éviter l'instanciation de la classe, on peut également la déclarer abstraite.
la source
Demandez-vous d'abord ce que cet objet va représenter? Une instance d'objet est idéale pour fonctionner sur des ensembles séparés de données dynamiques.
Un bon exemple serait l'ORM ou la couche d'abstraction de base de données. Vous pouvez avoir plusieurs connexions de base de données.
Ces deux connexions peuvent désormais fonctionner indépendamment:
Maintenant, dans ce package / bibliothèque, il peut y avoir d'autres classes telles que Db_Row, etc. pour représenter une ligne spécifique renvoyée par une instruction SELECT. Si cette classe Db_Row était une classe statique, cela supposerait que vous n'ayez qu'une seule ligne de données dans une base de données et qu'il serait impossible de faire ce qu'une instance d'objet pourrait faire. Avec une instance, vous pouvez désormais avoir un nombre illimité de lignes dans un nombre illimité de tables dans un nombre illimité de bases de données. La seule limite est le matériel du serveur;).
Par exemple, si la méthode getRows sur l'objet Db renvoie un tableau d'objets Db_Row, vous pouvez désormais opérer sur chaque ligne indépendamment les unes des autres:
Un bon exemple de classe statique serait quelque chose qui gère les variables de registre ou les variables de session car il n'y aura qu'un seul registre ou une session par utilisateur.
Dans une partie de votre candidature:
Et dans une autre partie:
Puisqu'il n'y aura qu'un seul utilisateur à la fois par session, il est inutile de créer une instance pour la session.
J'espère que cela aidera, ainsi que les autres réponses, à clarifier les choses. En remarque, consultez « cohésion » et « couplage ». Ils décrivent quelques très, très bonnes pratiques à utiliser lors de l'écriture de votre code qui s'appliquent à tous les langages de programmation.
la source
Si votre classe est statique, cela signifie que vous ne pouvez pas passer son objet à d'autres classes (car il n'y a pas d'instance possible), cela signifie que toutes vos classes utiliseront directement cette classe statique, ce qui signifie que votre code est maintenant étroitement couplé à la classe .
Un couplage étroit rend votre code moins réutilisable, fragile et sujet aux bogues. Vous voulez éviter les classes statiques pour pouvoir transmettre une instance de la classe à d'autres classes.
Et oui, ce n'est qu'une des nombreuses autres raisons dont certaines ont déjà été mentionnées.
la source
En général, vous devez utiliser des variables membres et des fonctions membres, sauf si elles doivent absolument être partagées entre toutes les instances ou à moins que vous ne créiez un singleton. L'utilisation de données membres et de fonctions membres vous permet de réutiliser vos fonctions pour plusieurs éléments de données différents, alors que vous ne pouvez avoir qu'une seule copie des données sur lesquelles vous opérez si vous utilisez des données et des fonctions statiques. De plus, bien que cela ne soit pas aussi applicable à PHP, les fonctions statiques et les données font que le code n'est pas réentrant, alors que les données de classe facilitent la réentrance.
la source
Je voudrais dire qu'il y a certainement un cas où je voudrais des variables statiques - dans des applications multilingues. Vous pourriez avoir une classe à laquelle vous passez une langue (par exemple $ _SESSION ['language']) et elle accède à son tour à d'autres classes qui sont conçues comme ceci:
L'utilisation de Strings :: getString ("somestring") est une bonne manière d'abstraire votre utilisation du langage de votre application. Vous pouvez le faire comme bon vous semble, mais dans ce cas, le fait que chaque fichier de chaînes ait des constantes avec des valeurs de chaîne auxquelles la classe Strings accède fonctionne plutôt bien.
la source