Page 1 sur 2
Accéder à des attributs protégés depuis une méthode statique
Posté : 20 juil. 2007, 13:00
par zeus
Bonjour à tous,
Je reviens vous voir pour m'aider à comprendre le fonctionnement OO de PHP5.
Lors d'un de mes développements, j'ai découvert qu'en PHP, dans une méthode statique d'une classe, d'accéder aux attributs protégés d'une instance de cette classe.
Comme un petit exemple vaut mieux qu'un grand discours, voici un exemple illustrant mes propos :
<?php
error_reporting(E_ALL); // Pour être sûr de voir toutes les erreurs, même les E_STRICT
class Statut
{
// *************
// *** Attributs de la classe
// *************
protected $code; // Ces attributs sont de visibilité "Protected"
protected $message;
// *************
// *** Méthode de la classe
// *************
static public function get_db_statut()
{ // Cette méthode est statique, donc pas d'instance de l'objet
// Instanciation du nouvel objet statut
$o_statut = new Statut();
// Modification des attributs de visibilité "Protected" de l'instance de la classe, créé dans la méthode
$o_statut->code = "Mon code";
$o_statut->message = "Mon message" ;
return $o_statut;
}
}
echo "Appel de la méthode statique<br />";
$o_statut = Statut::get_db_statut(); // Aucune erreur affichée
print_r($o_statut); // Les attributs de l'objet ont bien été affectés
echo "Modification d'un des attributs d'une instance de la classe<br />";
$o_statut = new Statut();
$o_statut->code = "Mon code"; // Modifications d'attributs de visibilité "protected"
$o_statut->message = "Mon message" ; // Une erreur intervient
Or, je sais qu'en Java et en C++, ce n'est pas possible de faire ça ...
J'aimerais donc que l'on m'explique pourquoi PHP l'implémente :S
Posté : 20 juil. 2007, 13:45
par Hubert Roksor
Je pense que tu as eu quelques problèmes de recopiage parce que
$o_statut = Statut::get_db_statut();
...est null (get_db_statut() ne renvoit rien) et j'ai une erreur à l'avant-dernière ligne, comme on pouvait s'y attendre.
Posté : 20 juil. 2007, 13:46
par Genova
Bonjour,
déjà vis à vis de l'error_reporting() E_STRICT n'est pas inclu dans E_ALL (il le devient à partir de PHP6). Donc pour bien voir toutes les erreurs :
(ce n'est pas le propos, mais c'était par rapport au commentaire dans ton fichier).
Ensuite à mon avis, PHP considère que les propriétés de tout objet déclaré dans un objet du même type sont accessibles. J'ai aussi fait le test avec une méthode non statique et PHP ne lache pas d'erreurs non plus apparament. Maintenant pourquoi ... peut être tout simplement parce que c'est la volonté de PHP d'agir comme ça ? Mais effectivement je ne trouve pas ça spécialement logique vis à vis de la protection des propriétés, d'autant plus que apparament ça marche aussi pour les private.
Posté : 20 juil. 2007, 13:53
par Hywan
Salut
Si on peut déclarer des méthodes en statique, c'est pour nous permettre de ne pas instancier. Donc déclarer une méthode statique, pour instancier son objet est un peu bête
J'aurais plutôt vue ça comme ça :
<?php
header('content-type: text/plain');
class StatusA {
protected static $code = null;
protected static $message = null;
public static function get_db_status ( ) {
self::$code = 'Mon code';
self::$message = 'Mon message';
return array(
self::$code,
self::$message);
}
}
$status = StatusA::get_db_status();
print_r($status);
// ou
class StatusB {
public static $code = null;
public static $message = null;
public static function get_db_status ( ) {
self::$code = 'Mon code';
self::$message = 'Mon message';
}
}
StatusB::get_db_status();
echo StatusB::$code . "\n" .
StatusB::$message . "\n\n";
StatusB::$code = 'Autre code';
StatusB::$message = 'Autre message';
echo StatusB::$code . "\n" .
StatusB::$message . "\n";
Tu remarques les différents types pour les propriétés (public et protected).
Affichera donc :
Code : Tout sélectionner
Array
(
[0] => Mon code
[1] => Mon message
)
Mon code
Mon message
Autre code
Autre message

Posté : 20 juil. 2007, 13:59
par Cyrano
Donc déclarer une méthode statique, pour instancier son objet est un peu bête

Pas obligatoirement : c'est comme ça qu'on crée un singleton, on crée un constructeur privé et une méthode statique de récupération d'instance de classe.
Posté : 20 juil. 2007, 14:04
par Genova
Idem pour le design pattern factory :
http://www.journaldunet.com/developpeur ... ry-2.shtml assez pratique d'ailleurs

Posté : 20 juil. 2007, 14:05
par Hywan
@Cyrano : Oui je suis au courant. Mais dans son cas c'est inutile, du moins, avec le code présenté.
Mais tu as raison de le souligner

Posté : 20 juil. 2007, 14:20
par zeus
@
Hubert : Effectivement, j'ai essayé d'alléger au maximum et je suis allé trop loin
La méthode get_db_statut() retourne l'instance de Statut qu'elle a instanciée. Je corrige mon code d'origine. Désolé
@
Genova : je ne savais pas, je prend note, merci
@
HyWaN : Tu as un exemple très allégé de ce que fait cette méthode. Dans celle d'origine, il est très intéressant de ne pas instancier l'objet
Cyrano et
Genova sont très proche de ce que fait la classe.
En fait, ma question ne porte pas tellement sur "est-ce que c'est possible ?", puisque j'ai découvert que ça l'était, mais plutôt "Quel est l'utilité ?", surtout que c'est un comportement propre à PHP qui est impossible en C++ ou en Java

Posté : 20 juil. 2007, 14:29
par Hywan
Tu parles du singleton là ?

Posté : 20 juil. 2007, 14:35
par Hywan
Le singleton est extrêmement pratique en fait.
Dans certain cas, ton objet ne doit être instancier qu'une seule et unique fois !
Par exemple, je travaille sur un MVC en ce moment. J'ai une classe qui se charge de dispatcher mes objets etc. Si mon objet est instancier plusieurs fois, on aura des soucis dans le dispatchage des objets. Donc on ne l'instancie qu'une seule et unique fois. Ca peut être utile aussi pour des connexions vers des tables etc.
Un petit exemple :
<?php
class Singleton {
private static $_instance = null;
private function __construct ( ) {
// on lance les instructions qui n'ont besoin d'être faite qu'une
// seule et unique fois !
}
public static function getInstance ( ) {
if(null === self::$_instance)
self::$_instance = new self();
return self::$_instance;
}
}
// on veut l'instance :
$singleton = Singleton::getInstance();
// on fait des opérations, des appels de méthodes etc.
// et si plus tard dans le code, on veut réavoir l'instance, on fait :
$singleton = Singleton::getInstance();
// l'objet ne sera pas recréé, mais l'instance sera retournée.
Edit : j'ai validé mon message sans faire exprès pour le précédent ... désolé.
Posté : 20 juil. 2007, 14:41
par zeus
Si ce que tu cherches à me dire c'est que c'est ce comportement qui permet la création de singleton, quel est le principe équivalent en Java ou C++ ?
Posté : 20 juil. 2007, 14:46
par Hywan
Je ne connais ni Java ni C++ ^^ Enfin, j'ai un niveau scolaire.
Mais j'ai appris le design pattern dans un livre pour Java, donc ça doit exister. Attends je regarde dan mon livre ... En fait, la syntaxe est la même, et on apelle ça le design pattern Singleton, ou aussi un objet unique.
Le pattern Singleton garandit qu'une classe n'a qu'une seule instance et fournit un point d'accès global à cette instance.
(chez O'Reilly)
Je ne vois pas ce que tu veux savoir de plus ?
Posté : 20 juil. 2007, 14:51
par zeus
J'ai mal compris ton code ...
Tu passes par un attribut statique, donc partager par toutes les instances de la classe, comme en Java et en C++.
Par contre, je ne vois pas l'intérêt de pouvoir accéder à un attribut non statique d'une instance de la classe dans une méthode statique de cette même classe.
Posté : 20 juil. 2007, 15:00
par Hywan
Tes questions me font mal à la tête.
Déjà, tu as compris le code maintenant ? Il faut savoir ce qu'on cherche. J'ai l'impression qu'on ne cherche pas la même chose
Par contre, je ne vois pas l'intérêt de pouvoir accéder à un attribut non statique d'une instance de la classe dans une méthode statique de cette même classe.
Je tente de traduire.
Tu ne vois pas l'intérêt de faire
$object->proprety dans une méthode statique de cette même classe. Donc
$object, peut être
$this (sauf certain cas). Hmm. Moi, j'y vois un intérêt, ce serait une récursivité dans les objets, avec les instances dans une propriété statique ou non statique d'ailleurs.
Est-ce que tu pourrais mettre un exemple plus parlant ? Je suis un peu perdu.
Je dois partir, j'ai un truc important à faire. Je continue à regarder ton code ce soir

(mais les autres peuvent participer

).
Posté : 20 juil. 2007, 15:08
par Genova
Le problème de zeus est simple, t'as une classe :
Code : Tout sélectionner
class Toto
{
protected $variable;
public static function titi()
{
$new_instance = new Toto;
$new_instance->variable = 'valeur';
}
}
et il se demande pourquoi on peut assigner une valeur à $new_instance->variable alors qu'il s'agit d'une propriété protégée.
Sachant que ce code ne marche que si on créé une instance de la classe en son sein (mais malgré le fait qu'elle soit en son sein, elle reste indépendante, et par conséquent les éléments protected ne devrait pas être accessible).