2010-01-09 7 views
5

Question éditée pour mieux refléter mes besoins.Méthodes de classe parent appel


Prenons l'exemple suivant:

class Base 
{ 
    public $Text = null; 

    public function __construct() 
    { 
     $this->Text = new Base_Text(); 
    } 
} 

class Base_Text extends Base 
{ 
    public $Is = null; 

    public function __construct() 
    { 
     $this->Is = new Base_Text_Is(); 
    } 

    public function CammelCase($string) 
    { 
     return trim(str_replace(' ', '', ucwords($string))); 
    } 
} 

class Base_Text_Is extends Base_Text 
{ 
    public function CammelCase($string) 
    { 
     return ($string === $this->CammelCase($string)); // doesn't work 
    } 
} 

Comment puis-je fixer la méthode Base_Text_Is::CammelCase() sans appeler la classe Base_Text statiquement (ne pas utiliser parent:: ou Base_Text::)?

La seule solution que je suis venu avec pour ce genre de situations est de créer une fonction singleton comme ceci:

function Base() 
{ 
    static $instance = null; 

    if (is_null($instance) === true) 
    { 
     $instance = new Base(); 
    } 

    return $instance; 
} 

Et changer la méthode Base_Text_Is::CammelCase() à ceci:

return ($string === Base()->Text->CammelCase($string)); 

Et pour pour éviter de créer deux instances d'objet de la classe Base, au lieu de:

$base = new Base(); 
$base->Text->Is->CammelCase('MethodOverloading'); // true 

Je fais juste:

Base()->Text->Is->CammelCase('MethodOverloading'); // true 

Est-ce une bonne pratique? Y a-t-il d'autres solutions?

+0

Je ne t obtenir votre dernier commentaire dans la réponse de Darrell. Vous n'êtes pas capable d'accéder aux propriétés non statiques de 'Base_Text'? D'où voulez-vous les appeler? Je pense que vous devriez expliquer cela plus en détail. –

+0

@Fixix: J'essaie de garder l'exemple aussi simple que possible, il y a des cas où je ne peux pas appeler une méthode parente de façon statique car cela dépend des propriétés instanciées. –

Répondre

7

Le cœur de votre question se trouve ici:

Comment Fils :: B() appeler le papa :: A() Méthode non statique (sans utiliser parent ou papa)?

La réponse est simplement, il ne peut pas. Vous avez dépassé Dad::A() avec Son::A(). Le seul concept de A() que l'objet Son a maintenant est son propre A(). Vous devrez appeler la méthode parent de manière statique, ou sur une instance d'objet complètement différente.

En bout de ligne, si vous voulez appeler la méthode parente A(), pourquoi prenez-vous la peine de la remplacer en premier lieu?

Votre structure n'a aucun sens non plus. Pourquoi voudriez-vous un appel à $dad->A() passer à $dad->son->A(), qui à son tour appellerait $dad->son->B(), qui ensuite, à partir de ce que vous demandez, appelez $dad->A() à nouveau? C'est une boucle infinie.Votre approche singleton ne semble pas offrir d'avantage réel si ce n'est de s'assurer que vous n'instanciez pas plus d'un objet dad, mais le fait est que vous instanciez toujours un objet complètement séparé pour exécuter une logique qui ressemble à il devrait être à l'intérieur de la classe et non à l'extérieur.

Sans voir la véritable logique et ce que vous essayez d'accomplir, il est difficile de savoir quoi recommander pour éviter cette dépendance circulaire. Cependant, je pense que vous pourriez vouloir analyser ce que vous essayez de faire avec ces méthodes et peut-être revoir la façon dont l'héritage fonctionne.

EDIT

Je pense que vous avez beaucoup trop d'héritage en cours. Il n'y a aucune raison que vous devez faire ceci:

$base = new Base(); 
$base->Text->Is->CammelCase('MethodOverloading'); // true 

Si toutes les fonctionnalités est dans les classes d'enfants, vous ne devriez pas être instancié avec la classe Base. Il devrait être quelque chose comme ceci:

$text = new Text(); 
$text->isCamelCase('someString'); 

Votre code peut être grandement simplifié, avec tous les instanciations parents circulaires/enfants enlevés et les fonctionnalités spécifiques poussé vers le bas aux classes d'enfants:

class Base 
{ 
    //don't put anything related to child classes here, 
    //unless it is going to provide specific functionality 
} 

class Text extends Base 
{ 
    public function CamelCase($string) 
    { 
     return trim(str_replace(' ', '', ucwords($string))); 
    } 

    public function isCamelCase($string) 
    { 
     return ($string === $this->CamelCase($string)); 
    } 
} 
+0

C'est un exemple hypothétique bien sûr, et je sais que c'est une boucle infinie. J'ai cependant rencontré des applications utiles dans le monde réel et j'ai toujours utilisé la solution que j'ai fournie dans ma question. Je me demandais juste s'il pourrait y avoir une meilleure alternative. –

+0

J'ai mis à jour la question pour donner un exemple plus réaliste et résoudre certains des problèmes que vous vous référez, comme "instancier un objet complètement séparé". J'espère que ça le rend un peu plus clair maintenant. –

+0

@zombat: Je voudrais juste demander, à la lumière de ma dernière édition, si vous pensez toujours que la re-conception de l'héritage est une bonne idée (si oui, des pointeurs?) Et si vous utilisez la fonction singleton 'Base()' une mauvaise pratique dans ce scénario. –

1

Je ne pense pas qu'il existe un moyen d'appeler une méthode parent de l'enfant sans l'appeler statiquement ou en utilisant parent::. Je peux mal comprendre la question cependant. La création d'une instance de Son() ne crée pas deux objets. Fils étend Papa mais son seul objet.

Si vous appelez Dad() avec un Singleton dans Son, alors pourquoi l'étendre à partir de Son?

+0

J'ai mis à jour ma question avec un exemple plus réaliste, veuillez le vérifier. –

+0

Je ne comprends toujours pas votre aversion à utiliser 'parent ::'. –

+0

Ce n'est pas une aversion, je ne peux pas l'utiliser parce que si je le fais, je ne serai pas en mesure d'accéder aux propriétés non statiques 'Base_Text'. –

Questions connexes