Précédent   Forum des professionnels en informatique > PHP > Langage > Syntaxe
Syntaxe Forum d'entraide sur la syntaxe de PHP et la POO. Avant de poster -> FAQ syntaxe, Cours d'initiation et cours de POO
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 07/01/2011, 19h25   #1
Membre à l'essai
 
Inscription : mars 2008
Messages : 48
Détails du profil
Informations forums :
Inscription : mars 2008
Messages : 48
Points : 24
Points : 24
Par défaut classe abstraite, classe concrete et héritage

Bonjour.

mon probleme est le suivant: une méthode statique définie dans une classe abstraite utilise une propriété définie dans la classe concrète qui l'implémente.

(PHP 5.2.6 sur le serveur)

ex. de code ne fonctionnant pas:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
interface INormalizer {
	public static function normalize($value);
}
 
abstract class Normalizer implements INormalizer {
 
	public static function normalize($value) {
		foreach (self::$a_convert as $k => $v) {
			if (in_array(strtolower($value), $v)) 
				return $k;
		}
		return null;
	}
}
 
class Normalizer_GameType extends Normalizer {
	public $a_convert = array(
		"SCB" => array ("scb", "scrabble"),
		"MNPLY" => array ("mnply", "monopoly")
	);
}
 
class Normalizer_GameInfo extends Normalizer {
	public $a_convert = array(
		"PRX" => array ("prx", "prix"),
		"WTV" => array ("wtv", "whatever")
	);
}
Un
Code :
var_dump(Normalizer_GameInfo::normalize("juju"));
renvoie

Fatal error: Access to undeclared static property: Normalizer::$a_convert in C:\www\test.php on line 9

Comment faire?

Merci d'avance pour votre aide.
danidan75 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/01/2011, 20h40   #2
Rédacteur/Modérateur
 
Avatar de MaitrePylos
 
Homme Gérard Ernaelsten
DBA & Dev PHP
Inscription : juin 2005
Messages : 3 174
Détails du profil
Informations personnelles :
Nom : Homme Gérard Ernaelsten
Âge : 39
Localisation : Belgique

Informations professionnelles :
Activité : DBA & Dev PHP
Secteur : Service public

Informations forums :
Inscription : juin 2005
Messages : 3 174
Points : 6 460
Points : 6 460
Dans ta classe abstraite, tu ne définis pas en static $a_convert, en fait tu ne le définis pas du tout

Une classe mère, ne connais pas les attributs d'une classe fille !
MaitrePylos est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/01/2011, 21h40   #3
Membre à l'essai
 
Inscription : mars 2008
Messages : 48
Détails du profil
Informations forums :
Inscription : mars 2008
Messages : 48
Points : 24
Points : 24
Certes, mais la méthode normalize est commune à toutes les classes concrète (c'est pourquoi je la défini dans la classe abstraite, pour ne pas dupliquer le code). Par contre, $a_convert est spécifique à chaque classe concrète.
A la lumière de ces données (méthode identique, propriété différente), comment coder ça proprement?
Merci d'avance.
danidan75 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/01/2011, 00h10   #4
Expert Confirmé
 
Avatar de rawsrc
 
Homme Martin
Dev indep
Inscription : mars 2004
Messages : 1 461
Détails du profil
Informations personnelles :
Nom : Homme Martin
Âge : 35
Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

Informations professionnelles :
Activité : Dev indep

Informations forums :
Inscription : mars 2004
Messages : 1 461
Points : 2 548
Points : 2 548
Envoyer un message via Skype™ à rawsrc
Salut danidan75,

Bon c'est simple ce que tu veux faire est impossible avant PHP 5.3.
Je t'invite à regarder du côté du LSB : Late Static Binding.
Cette fonctionnalité te permet de remonter les valeurs de variables statiques définies dans des classes dérivées à des classes parentes.
Très pratique dans le cadre d'un Framework, enfin dans ma boite on utilise ceci massivement

En PHP 5.3 cela donnerait dans ton cas :
Ici, à l'exécution du code de la classe mère (abstract dans ton cas) le moteur du PHP irait chercher la valeur statique de ta variable là où elle est définie et la ramenerait dans le corps de la fonction de la classe parente.

Bon si tu ne peux pas passer sous une version récente du PHP, tu peux contourner cette limitation en modifiant légèrement ton interface.
Au lieu d'avoir une variable, il te faudrait transformer $a_convert en a_convert().

Espérant avoir été assez clair à miniuit.
rawsrc est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/01/2011, 09h52   #5
Rédacteur/Modérateur
 
Avatar de MaitrePylos
 
Homme Gérard Ernaelsten
DBA & Dev PHP
Inscription : juin 2005
Messages : 3 174
Détails du profil
Informations personnelles :
Nom : Homme Gérard Ernaelsten
Âge : 39
Localisation : Belgique

Informations professionnelles :
Activité : DBA & Dev PHP
Secteur : Service public

Informations forums :
Inscription : juin 2005
Messages : 3 174
Points : 6 460
Points : 6 460
Je confirme que ceci en 5.3 fonctionne
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 
interface INormalizer {
	public static function normalize($value);
}
 
abstract class Normalizer implements INormalizer {
 
	public static $a_convert ;	
	public static function normalize($value) {
		foreach (static::$a_convert as $k => $v) {
			if (in_array(strtolower($value), $v)) 
				return $k;
		}
		return null;
	}
}
 
class Normalizer_GameType extends Normalizer {
	public static $a_convert = array(
		"SCB" => array ("scb", "scrabble"),
		"MNPLY" => array ("mnply", "monopoly")
	);
}
 
class Normalizer_GameInfo extends Normalizer {
	public static $a_convert = array(
		"PRX" => array ("prx", "prix"),
		"WTV" => array ("wtv", "whatever")
	);
 
}
En 5.2, il fait mettre des getters et setters
MaitrePylos est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/01/2011, 11h11   #6
Membre à l'essai
 
Inscription : mars 2008
Messages : 48
Détails du profil
Informations forums :
Inscription : mars 2008
Messages : 48
Points : 24
Points : 24
Une subtilité doit m'échapper
Comme proposé, je suis passé par un getter, et le nouveau code est
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?php
interface INormalizer {
	public static function normalize($value);
	public function getConvertArray();
}
 
abstract class Normalizer implements INormalizer {
 
	public static function normalize($value) {
		foreach (self::getConvertArray() as $k => $v) {
			if (in_array(strtolower($value), $v)) 
				return $k;
		}
		return null;
	}
}
 
class Normalizer_GameType extends Normalizer {
	public function getConvertArray() {
		return array(
			"SCB" => array ("scb", "scrabble"),
			"MNPLY" => array ("mnply", "monopoly")
		);
	}
}
 
class Normalizer_GameInfo extends Normalizer {
	public function getConvertArray() {
		return array(
			"PRX" => array ("prx", "prix"),
			"WTV" => array ("wtv", "whatever")
		);
	}
}
var_dump(Normalizer_GameInfo::normalize("robert"));
?>
En fait, cela déplace le problème, mon nouveau message d'erreur est
Code :
Fatal error: Cannot call abstract method INormalizer::getConvertArray() in C:\www\test.php on line 10
P.S.: PHP 5.3, je voudrais bien, mais non, le serveur est en 5.2 et aucune migration n'est prévue à court terme.
danidan75 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/01/2011, 13h49   #7
Expert Confirmé
 
Avatar de rawsrc
 
Homme Martin
Dev indep
Inscription : mars 2004
Messages : 1 461
Détails du profil
Informations personnelles :
Nom : Homme Martin
Âge : 35
Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

Informations professionnelles :
Activité : Dev indep

Informations forums :
Inscription : mars 2004
Messages : 1 461
Points : 2 548
Points : 2 548
Envoyer un message via Skype™ à rawsrc
Bonjour,

Autant pour moi, je n'ai pas suffisamment été clair, désolé.
Oui j'aurais dû te dire que hors de PHP 5.3, il t'est impossible de traiter ce cas de figure dans le monde static.

Pour y arriver en 5.2 et en faisant simple tu n'as pas le choix que de passer par le polymorphisme ou comme le dis MaitrePylos en utilisant le getter/setter mais dans ce cas cela va alourdir légèrement le code. Qui dit getter/setter dit instance et donc bye bye le monde static.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?php 
 
interface INormalizer {
   public function normalize($value);
   public function getConvertArray();
}
 
abstract class Normalizer implements INormalizer {
 
   public function normalize($value) {
      foreach ($this->getConvertArray() as $k => $v) {
         if (in_array(strtolower($value), $v)) 
            return $k;
      }
      return null;
   }
}
 
class Normalizer_GameType extends Normalizer {
   public function getConvertArray() {
      return array(
         "SCB" => array ("scb", "scrabble"),
         "MNPLY" => array ("mnply", "monopoly")
      );
   }
 
}
 
class Normalizer_GameInfo extends Normalizer {
   public function getConvertArray() {
      return array(
         "PRX" => array ("prx", "prix"),
         "WTV" => array ("wtv", "whatever")
      );
   }
}
 
$n = new Normalizer_GameInfo();
$n->normalize('robert');
 
?>
rawsrc est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/01/2011, 14h14   #8
Membre à l'essai
 
Inscription : mars 2008
Messages : 48
Détails du profil
Informations forums :
Inscription : mars 2008
Messages : 48
Points : 24
Points : 24
Effectivement, Xysio, à un moment, je m'étais demandé si la fonction a_convert dont tu me parlais était hors classe, et donc accessibles de partout.
Au final, s'il est impossible de passer par une methode statique, je prends
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
interface INormalizer {
	public function normalize($value);
}
 
abstract class Normalizer implements INormalizer {
 
	public function normalize($value) {
		foreach ($this->a_convert as $k => $v) {
			if (in_array(strtolower($value), $v)) 
				return $k;
		}
		return null;
	}
}
 
class Normalizer_GameType extends Normalizer {
	public $a_convert = array(
		"SCB" => array ("scb", "scrabble"),
		"MNPLY" => array ("mnply", "monopoly")
	);
}
 
class Normalizer_GameInfo extends Normalizer {
	public $a_convert = array(
		"PRX" => array ("prx", "prix"),
		"WTV" => array ("wtv", "whatever")
	);
}
$normalizer_gameinfo = new Normalizer_GameInfo();
var_dump($normalizer_gameinfo->normalize("robert"));
var_dump($normalizer_gameinfo->normalize("whatever"));
 
?>
Merci à tous pour votre aide.
danidan75 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 17h59.


 
 
 
 
Partenaires

Hébergement Web