2010-09-13 5 views
3

J'ai étudié en php oop et stocké dans le concept de code réutilisable.PHP: comment réutiliser le code (oop)?

J'ai vu un exemple comme

interface iTemplate 
{ 
    public function setVariable($name, $var); 
    public function getHtml($template); 
} 
And implement it: 

// Implement the interface 
class Template implements iTemplate 
{ 
    private $vars = array(); 

    public function setVariable($name, $var) 
    { 
     $this->vars[$name] = $var; 
    } 

    public function getHtml($template) 
    { 
     foreach($this->vars as $name => $value) { 
      $template = str_replace('{' . $name . '}', $value, $template); 
     } 

     return $template; 
    } 
} 

Je peux comprendre le code, mais ne sais pas pourquoi il est réutilisable. Chaque fois que je veux ajouter une nouvelle fonction dans l'interface iTemplate, ma classe Template doit également être modifiée. Je ne comprends pas le concept de "réutilisation". J'apprécie toute aide. Merci.

+0

pouvez-vous me dire où avez-vous trouvé ce code? Je suis dans la phase d'apprentissage et je cherche à apprendre par des exemples. – dole

Répondre

6

Les interfaces ne sont pas directement utilisées pour la réutilisation du code. Ils sont pour l'abstraction. Ils permettent aux classes qui utilisent le modèle de vérifier l'interface au lieu de la classe de modèle de base. De cette façon, il sépare l'implémentation de la déclaration d'interface. Par conséquent, si votre méthode fait quelque chose avec une classe template, la vérification d'un objet de l'instance template permet de coder en dur une dépendance sur cette classe. Mais en réalité vous ne vous souciez pas de la classe que vous obtenez, vous vous souciez seulement si elle adhère à l'interface iTemplate (puisque c'est tout ce que vous appelez de toute façon).

public function foo(Template $template) { 

vs:

public function foo(iTemplate $template) { 

Maintenant, dans la mesure où le code de réutilisation, les interfaces ne sont pas vraiment conçus pour cela. L'héritage est généralement. Fondamentalement, pensez à l'héritage comme l'extension d'une abstraction. Permettez-moi de vous donner un exemple:

Si vous deviez créer un ensemble de classes pour les oiseaux, vous pourriez l'aborder avec l'héritage et sans elle. Voyons voir comment nous pourrions le faire sans:

interface iBird { 
    public function fly(); 
    public function speak(); 
    public function swim(); 
    public function walk(); 
} 

class Duck implements iBird { 
    public function fly() { 
     //Fly here 
    } 
    public function speak() { 
     // Quack here 
    } 
    public function swim() { 
     //Swim here 
    } 
    public function walk() { 
     //Walk here 
    } 
} 

class Turkey implements iBird { 
    public function fly() { 
     //Fly here, but limited 
    } 
    public function speak() { 
     //Make turkey sound here 
    } 
    public function swim() { 
     throw new Exception('Turkeys can not swim!'); 
    } 
    public function walk() { 
     //Walk here 
    } 
} 

Maintenant, ceci est un exemple simple, mais vous pouvez voir que dans ces deux oiseaux, les walk() fonctions seront probablement identiques (et elle contreviendrait ainsi DRY) ...

Voyons comment cela pourrait ressembler à un seul héritage de niveau:

abstract class Bird implements iBird { 
    public function fly() { 
     //Fly here 
    } 
    abstract public function speak(); 
    public function swim() { 
     //Swim here 
    } 
    public function walk() { 
     //Walk here 
    } 
} 

class Duck extends Bird { 
    public function speak() { 
     //Quack here 
    } 
} 

class Turkey extends Bird { 
    public function speak() { 
     //Make turkey sound here 
    } 
    public function swim() { 
     throw new Exception('Turkeys can not swim!'); 
    } 
} 

maintenant, vous pouvez voir que nous venons de rÉUTILISÉS 3 des méthodes! Nous n'avons pas déclaré speak(), car il sera toujours dépassé (puisque deux oiseaux ne se ressemblent pas).

Ça a l'air bien, non? Eh bien, en fonction de nos besoins, nous pouvons vouloir ajouter d'autres types abstraits. Disons donc que nous faisions beaucoup de différents types d'oiseaux ... Nous en aurions certains qui ne nageraient pas, donc nous pourrions créer une classe abstraite NonSwimmingBird qui étend Bird, mais qui jette l'exception pour nous. Ou un NonFlyingBird, ou un ShortRangeBird ...

Maintenant, nous sommes vraiment sur la piste en ce qui concerne la réutilisation du code, mais nous touchons un mur dans une autre zone. Supposons que nous ayons un oiseau qui ne vole pas ou nage. De quelle classe héritons-nous? De toute façon, nous dupliquons le code. Nous devons donc trouver une autre issue. Eh bien, comment le faisons-nous? Grâce à Design Patterns ... Au lieu de l'héritage direct, nous pourrions utiliser un modèle de décorateur pour ajouter ces traits à la volée. (Il y a d'autres modèles qui peuvent être utilisés ici, le but est de montrer que l'héritage seul ne répondra pas à tous les besoins.) Et les patterns ne le seront pas non plus Vous avez besoin d'une bonne architecture utilisant les deux mondes selon vos besoins ...

Le fait est que tout dépend de vos besoins. Si vous n'avez que 2 "classes" d'objets, vous allez construire quelque chose de beaucoup plus simple que si vous prévoyez en avoir des milliers. Le but de ce que j'ai écrit ici est de démontrer comment vous pouvez utiliser l'héritage direct pour appliquer certains principes DRY (mais aussi comment l'héritage direct peut aussi entraîner une duplication de code). La grande chose, c'est de ne pas essayer de rester sur DRY juste parce que vous ne voulez pas vous répéter. Stick à DRY, mais assurez-vous que vous combinez et d'étendre là où c'est raisonnable, sinon vous vous créez un mal de tête de maintenance. Stick à la Single Responsibility Principal, et vous devriez être bien ...

+0

très très belle explication .... merci un million. – FatDeveloper

0

L'interface écrit seulement 1 fois en début de développement. Et seulement après cela écrit d'autres classes implémente de cette Interface. Interface - est un fondement. Remarque: la méthode setVariable n'est pas requise. Il existe de bonnes méthodes magiques en PHP comme __get(), et __set().

+0

Merci. mais disons que nous créons une autre classe appelée Product implement iTemplate. Je dois encore taper la méthode setVariable et getHtml dans ma classe avec ou sans interface d'implémentation, alors à quoi ça sert? – FatDeveloper

0

Les interfaces sont généralement utiles dans les cas où vous voulez que quelque chose soit interchangeable. Imaginez que vous construisiez une application prenant en charge les plugins. Vous avez alors l'interface iPlugin:

interface iPlugin { 
    public function init(); 
    /* .. */ 
} 

et tous les plugins implémenteraient cette interface. Un gestionnaire de plugins peut alors facilement vérifier si un plugin implémente l'interface et appelle la méthode init() dessus.

0

Le code n'a pas besoin d'être OO pour être réutilisable, bien que dans de nombreux cas cela aide.

Le code n'a certainement pas besoin d'utiliser des interfaces pour être réutilisable, bien que dans certains cas cela puisse aider. La clé de l'écriture de code réutilisable consiste à écrire un code clairement écrit, bien commenté, qui utilise des conventions de nommage et d'appel cohérentes et qui est plus général qu'il ne devrait l'être pour le problème en question.

L'une des techniques les plus simples et les plus puissantes pour écrire du code réutilisable en PHP est l'écriture de méthodes acceptant un nombre variable d'arguments ou acceptant un tableau associatif de paramètres.

Souvent, le code qui n'a pas commencé "intending" pour être réutilisable s'avère être quelque chose que vous voudrez réutiliser. Généralement, le code commence "en ligne" et vous découvrez que vous devez faire exactement, ou presque exactement, la même chose à plus d'un endroit. Lorsque vous vous retrouvez à copier et coller du code, il est temps de le refactoriser en tant que fonction. De même, quand vous avez besoin d'une fonction que vous avez définie dans le fichier X, ce serait vraiment utile dans le fichier Y, il est temps de le déplacer dans un module.

La meilleure façon d'apprendre tout cela est par l'expérience. Certaines personnes vous diront d'architecturer ces choses dès le début, et c'est certainement une bonne idée si vous avez la perspicacité et l'expérience pour le faire, mais c'est tout aussi valable de le faire, et c'est probablement la meilleure façon de apprendre.

0

Réutilisable de la programmation orientée objet est l'utilisation de la classe précédente ou d'une fonction ou méthode dans la classe actuelle, mais aucun problème de la classe précédente.