Après avoir activé les avertissements stricts dans PHP 5.2, j'ai vu une foule d'avertissements de normes strictes d'un projet qui a été initialement écrit sans avertissements stricts:
Standards stricts : la fonction statique Program :: getSelectSQL () ne doit pas être abstraite dans Program.class.inc
La fonction en question appartient à une classe parent abstraite Program et est déclarée statique abstraite car elle doit être implémentée dans ses classes enfants, telles que TVProgram.
J'ai trouvé des références à ce changement ici :
Suppression des fonctions de classe statique abstraite. En raison d'un oubli, PHP 5.0.x et 5.1.x ont autorisé les fonctions statiques abstraites dans les classes. Depuis PHP 5.2.x, seules les interfaces peuvent les avoir.
Ma question est la suivante: quelqu'un peut-il expliquer clairement pourquoi il ne devrait pas y avoir de fonction statique abstraite en PHP?
Réponses:
les méthodes statiques appartiennent à la classe qui les a déclarées. Lors de l'extension de la classe, vous pouvez créer une méthode statique du même nom, mais vous n'implémentez pas en fait une méthode abstraite statique.
Il en va de même pour l'extension de toute classe avec des méthodes statiques. Si vous étendez cette classe et créez une méthode statique de la même signature, vous ne remplacez pas réellement la méthode statique de la superclasse
EDIT (16 septembre 2009)
Mise à jour à ce sujet. En exécutant PHP 5.3, je vois que la statique abstraite est de retour, pour le meilleur ou pour le pire. (voir http://php.net/lsb pour plus d'informations)
La CORRECTION (par philfreo)
abstract static
n'est toujours pas autorisée en PHP 5.3, le LSB est lié mais différent.la source
abstract static
peut être utile dans ce cas.C'est une histoire longue et triste.
Lorsque PHP 5.2 a introduit cet avertissement pour la première fois, les liaisons statiques tardives n'étaient pas encore dans le langage. Si vous n'êtes pas familier avec les liaisons statiques tardives, notez qu'un code comme celui-ci ne fonctionne pas comme prévu:
Laissant de côté l'avertissement de mode strict, le code ci-dessus ne fonctionne pas. L'
self::bar()
appel enfoo()
fait explicitement référence à labar()
méthode deParentClass
, même lorsqu'ellefoo()
est appelée en tant que méthode deChildClass
. Si vous essayez d'exécuter ce code avec le mode strict désactivé, vous verrez " Erreur fatale PHP: impossible d'appeler la méthode abstraite ParentClass :: bar () ".Compte tenu de cela, les méthodes statiques abstraites de PHP 5.2 étaient inutiles. L' intérêt d'utiliser une méthode abstraite est que vous pouvez écrire du code qui appelle la méthode sans savoir quelle implémentation elle va appeler - puis fournir différentes implémentations sur différentes classes enfants. Mais puisque PHP 5.2 n'offre aucun moyen propre d'écrire une méthode d'une classe parente qui appelle une méthode statique de la classe enfant sur laquelle elle est appelée, cette utilisation de méthodes statiques abstraites n'est pas possible. Par conséquent, toute utilisation de
abstract static
PHP 5.2 est un mauvais code, probablement inspiré par une mauvaise compréhension du fonctionnement duself
mot clé. Il était tout à fait raisonnable de jeter un avertissement à ce sujet.Mais ensuite PHP 5.3 est venu ajouté dans la possibilité de faire référence à la classe sur laquelle une méthode a été appelée via le
static
mot - clé (contrairement auself
mot - clé, qui fait toujours référence à la classe dans laquelle la méthode a été définie ). Si vous passezself::bar()
àstatic::bar()
dans mon exemple ci-dessus, cela fonctionne bien dans PHP 5.3 et supérieur. Vous pouvez en savoir plus surself
vsstatic
à New self vs new static .Avec le mot clé static ajouté, l'argument clair pour avoir
abstract static
lancé un avertissement avait disparu. Le but principal des liaisons statiques tardives était de permettre aux méthodes définies dans une classe parente d'appeler des méthodes statiques qui seraient définies dans des classes enfants; autoriser des méthodes statiques abstraites semble raisonnable et cohérente étant donné l'existence de liaisons statiques tardives.Vous pourriez encore, je suppose, plaider pour le maintien de l'avertissement. Par exemple, vous pourriez soutenir que puisque PHP vous permet d'appeler des méthodes statiques de classes abstraites, dans mon exemple ci-dessus (même après l'avoir corrigé en le remplaçant
self
parstatic
) vous exposez une méthode publiqueParentClass::foo()
qui est cassée et que vous ne voulez pas vraiment exposer. Utiliser une classe non statique - c'est-à-dire faire de toutes les méthodes des méthodes d'instance et faire des enfants deParentClass
tous des singletons ou quelque chose - résoudrait ce problème, carParentClass
étant abstrait, ne peut pas être instancié et donc ses méthodes d'instance ne peuvent pas être appelé. Je pense que cet argument est faible (car je pense qu'exposerParentClass::foo()
n'est pas un gros problème et utiliser des singletons au lieu de classes statiques est souvent inutilement verbeux et laid), mais vous pourriez raisonnablement être en désaccord - c'est un appel quelque peu subjectif.Donc, sur la base de cet argument, les développeurs PHP ont gardé l'avertissement dans le langage, non?
Euh, pas exactement .
Le rapport de bogue PHP 53081, lié ci-dessus, demandait que l'avertissement soit supprimé car l'ajout de la
static::foo()
construction avait rendu les méthodes statiques abstraites raisonnables et utiles. Rasmus Lerdorf (créateur de PHP) commence par qualifier la demande de fausse et passe par une longue chaîne de mauvais raisonnement pour essayer de justifier l'avertissement. Puis, enfin, cet échange a lieu:L'affirmation de Rasmus selon laquelle le code de son exemple "fonctionne bien" est fausse; comme vous le savez, il lance un avertissement de mode strict. Je suppose qu'il testait sans le mode strict activé. Quoi qu'il en soit, un Rasmus confus a laissé la demande fermée à tort comme "bidon".
Et c'est pourquoi l'avertissement est toujours dans la langue. Ce n'est peut-être pas une explication entièrement satisfaisante - vous êtes probablement venu ici en espérant qu'il y avait une justification rationnelle de l'avertissement. Malheureusement, dans le monde réel, les choix naissent parfois d'erreurs banales et de mauvais raisonnements plutôt que d'une prise de décision rationnelle. C'est simplement l'un de ces moments.
Heureusement, l'estimable Nikita Popov a supprimé l'avertissement du langage en PHP 7 dans le cadre des notifications PHP RFC: Reclassify E_STRICT . En fin de compte, la raison a prévalu, et une fois que PHP 7 est sorti, nous pouvons tous l'utiliser avec plaisir
abstract static
sans recevoir cet avertissement stupide.la source
Il existe une solution très simple pour résoudre ce problème, ce qui est en fait logique du point de vue de la conception. Comme l'a écrit Jonathan:
Donc, pour contourner le problème, vous pouvez le faire:
Et maintenant vous faites en sorte que toute classe sous-classant MyFoo implémente une méthode statique getInstance et une méthode publique getSomeData. Et si vous ne sous-classez pas MyFoo, vous pouvez toujours implémenter iMyFoo pour créer une classe avec des fonctionnalités similaires.
la source
static::
peuvent être utiles.abstract static
méthodes, sans râler PHP ...Je sais que c'est vieux mais ...
Pourquoi ne pas simplement lancer une exception à la méthode statique de cette classe parente, de cette façon si vous ne la remplacez pas, l'exception est provoquée.
la source
Je dirais qu'une classe / interface abstraite pourrait être vue comme un contrat entre programmeurs. Il traite davantage de l'apparence / du comportement des choses et non de la mise en œuvre des fonctionnalités réelles. Comme on le voit dans php5.0 et 5.1.x, ce n'est pas une loi naturelle qui empêche les développeurs de php de le faire, mais l'envie d'aller avec d'autres modèles de conception OO dans d'autres langues. Fondamentalement, ces idées essaient d'éviter un comportement inattendu, si l'on est déjà familier avec d'autres langues.
la source
Je ne vois aucune raison d'interdire les fonctions abstraites statiques. Le meilleur argument selon lequel il n'y a aucune raison de les interdire est qu'ils sont autorisés en Java. Les questions sont les suivantes: - Est-ce techniquement faisable? - Oui, car ils existaient en PHP 5.2 et ils existent en Java. Alors, où PEUT le faire. Devrions-nous le faire? - Ont-ils un sens? Oui. Il est logique d'implémenter une partie d'une classe et de laisser une autre partie d'une classe à l'utilisateur. Cela a du sens dans les fonctions non statiques, pourquoi cela n'aurait-il pas de sens pour les fonctions statiques? Une utilisation des fonctions statiques sont les classes où il ne doit pas y avoir plus d'une instance (singletons). Par exemple, un moteur de chiffrement. Il n'a pas besoin d'exister dans plusieurs instances et il y a des raisons de l'empêcher - par exemple, vous ne devez protéger qu'une partie de la mémoire contre les intrus. Il est donc parfaitement logique d'implémenter une partie du moteur et de laisser l'algorithme de cryptage à l'utilisateur. Ceci n'est qu'un exemple. Si vous êtes habitué à utiliser des fonctions statiques, vous en trouverez beaucoup plus.
la source
En php 5.4+, utilisez le trait:
et dans votre classe, mettez au début:
la source
abstract public static function get_table_name();
un trait et l'utiliser dans ma classe abstraite sans plus d'avertissements E_STRICT! Cela imposait toujours la définition de la méthode statique chez les enfants comme je l'avais espéré. Fantastique!Examinez les problèmes de «liaison statique tardive» de PHP. Si vous mettez des méthodes statiques sur des classes abstraites, vous allez probablement y tomber plus tôt que tard. Il est logique que les avertissements stricts vous indiquent d'éviter d'utiliser des fonctionnalités de langage brisées.
la source