2009-12-29 9 views
0

J'ai une classe de collection générique, avec une variété de méthodes getter publiques.Substituez la méthode publique dans la sous-classe d'une manière qui restreint l'accès public tout en autorisant l'accès de la classe parent?

Pour obtenir un article de la collection, vous appelez get(). Il existe également plusieurs méthodes qui renvoient plusieurs éléments: getMany(), getRange(), getAll(), find(), findAll(), query(), queryAny(), etc.

En interne, toutes ces méthodes que retour plusieurs éléments ont une boucle qui appelle get() à plusieurs reprises, car ils regroupent les éléments individuels à retourner.

Un exemple simplifié:

public function get($key){ 
    return $this->collection[$key]; 
} 

public function getMany($keys){ 

    $many = array(); 

    foreach ($keys as $key){ 
     $many[] = $this->get($key); 
    } 

    return $many; 
} 

Le problème se pose quand je veux étendre Collection de telle sorte que je ne veux pas le client pour être en mesure d'accéder à un seul élément de la collection. Fondamentalement, je veux interdire l'accès à la méthode get().

Je ne peux pas faire de get() une fonction privée ou protégée, car elle est publique dans la classe parente. Je ne peux pas surcharger get() d'une manière qui le rende non fonctionnel (ie le remplacer par un simple retour, ou lancer une exception), car toutes les autres méthodes s'appuient sur get(), et Je veux qu'ils restent fonctionnels.

Je sais que je pourrais simplement remplacer toutes les méthodes qui dépendent de get() pour s'appuyer sur une nouvelle méthode protégée (c'est-à-dire getOne()), mais cela viole les principes DRY.

QU'EST-CE QUE JE NE VEUX PAS FAIRE:

class DataSet extends Collection{ 

    public function get(){ 
     throw new Exception('get() not implemented in DataSet'); 
    } 

    protected function getOne($key){ 
     return parent::get($key); 
    }  

    public function getMany($keys){ 

     $many = array(); 

     foreach ($keys as $key){ 
      $many[] = $this->getOne($key); 
     } 

     return $many; 
    } 
} 

Si je ne précède, je dois passer outre une demi-douzaine de méthodes (qui sont assez complexes en partie), et ils 'd ne diffère de la méthode de la classe parent que par quelques caractères.

Alors ... quelles autres options ai-je? Y a-t-il différents moyens à la même fin ...?

Répondre

3

Ce que vous pouvez faire est de faire une méthode protégée dites _get et cela peut être ce que toutes les méthodes appellent en interne. Vous pouvez ensuite exposer une méthode get sur toutes les classes qui ont besoin d'accès et l'appeler _get.

+0

D'oh! C'était la solution, cachée à la vue. Tous mes efforts étaient axés sur la recherche de solutions dans la sous-classe - je n'avais pas envisagé de changer la classe parente. Merci! –