2010-09-13 84 views
3

我已经研究了PHP的操作系统和可重用代码的概念。PHP:如何重用代码(oop)?

我已经见过像

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; 
    } 
} 

一个例子,我可以理解的代码,但不知道为什么它是可重复使用。每次我想在iTemplate界面添加一个新功能时,我的Template类也需要改变。我不明白“重用”的概念。我感谢任何帮助。谢谢。

+0

你能告诉我你在哪里找到那个代码吗?我正处于学习阶段,我希望通过实例学习。 – dole 2011-02-25 18:27:04

回答

6

接口是不能直接用于代码重用。他们是为了抽象。它们启用使用该模板的类来检查接口而不是基本模板类。这样它就将接口声明中的实现分开了。

因此,如果您的方法对template类执行了某些操作,那么检查实例template的对象将难以编码对该类的依赖性。但事实上,你并不在乎你得到的是什么课程,你只是在乎它是否遵守了界面(因为这就是你所打的所有东西)。

public function foo(Template $template) { 

VS:

public function foo(iTemplate $template) { 

现在,只要代码复用,接口是不是真的设计了点。继承通常是。基本上认为继承是扩展抽象。让我举个例子:

如果你要为鸟类创建一组类,你可以通过继承来处理它,如果没有它的话。让我们来看看我们如何做到这一点没有:

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 
    } 
} 

现在,这是一个简单的例子,但是你可以看到,在这两个鸟,walk()功能将可能是相同的(并因此违反DRY)...

让我们来看看如何看起来与单层继承:

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!'); 
    } 
} 

现在,你可以看到,我们只是重新使用的方法3!我们没有声明speak(),因为它会一直被覆盖(因为没有两只鸟听起来一样)。

听起来不错吧?那么,根据我们的需要,我们可能需要添加其他抽象类型。因此,我们可以说我们制作了许多不同类型的鸟类......我们会有一些不会游泳的,因此我们可能会创建一个抽象类NonSwimmingBird,它扩展Bird,但是会为我们引发异常。或者NonFlyingBirdShortRangeBird ...

现在,尽管代码重用,但我们在其他区域遇到了问题。假设我们有一只不会飞翔或游泳的鸟。我们继承什么课程?无论哪种方式,我们都在复制代码。所以我们需要找到另一条出路。那么,我们该怎么做呢?通过Design Patterns ...我们可以使用装饰器模式来实时添加这些特征,而不是直接继承。 (还有其他的模式可以用在这里,重点是要证明单独的继承并不适合所有的需求,单独的模式也不会,你需要一个好的架构来根据你的确切需求来使用两个世界) ...

问题是,这一切都取决于您的需求。如果你只有2个“班级”的对象,那么你将构建一个比如果你计划拥有数千个更简单的东西。我写在这里的目的是为了演示如何使用直接继承来实施一些DRY主体(但也包括直接继承如何导致代码重复)。最重要的是,不要因为你不想重复自己而坚持DRY。坚持DRY,但要确保你在合理的地方进行组合和扩展,否则你会造成自己的维护头痛。坚持Single Responsibility Principal,你应该没问题...

+0

非常非常好的解释....感谢一百万。 – FatDeveloper 2010-09-13 19:31:27

0

接口只写1处于发展的开始时间。只有在写这个接口的其他类实现之后。界面 - 是一个基础。 注意:方法setVariable不是必需的。 PHP中有很多神奇的方法,如__get()__set()

+0

谢谢。但是假设我们创建了另一个名为Product implement iTemplate的类。我仍然需要在类中输入setVariable和getHtml方法,不管是否实现接口,所以有什么意义? – FatDeveloper 2010-09-13 16:21:25

0

接口通常在你想要的东西是可以互换的情况下非常有用。想象一下你会构建一个支持插件的应用程序。然后你有接口iPlugin:

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

和所有的插件将实现该接口。然后,插件管理器可以轻松检查插件是否实现了接口并调用其上的init()方法。

0

代码并不需要是OO受到重用,但在很多情况下没有什么帮助。

代码当然不需要在某些情况下,这将有助于使用接口是可重复使用的,虽然一次。

编写可重用代码的关键是编写明确编写的代码,经过充分评论,使用一致的命名和调用约定,而且比通常需要解决的问题更为通用。

在PHP中编写可重用代码的最简单和最强大的技术之一是编写接受可变数量参数或接受参数关联数组的方法。

通常情况下,没有开始“打算”重新使用的代码就是您想要重用的东西。通常情况下,代码开始“内联”,然后你发现你需要在不止一个地方完全或几乎完全相同的事情。当你发现自己复制和粘贴代码时,是时候将它重构为一个函数。

同样,当你发现自己希望在文件X中定义的函数在文件Y中真正有用时,是时候将它移动到模块中。

学习这一切的最好方法是通过经验。有些人会告诉你从一开始就设计这些东西,如果你有这样的洞察力和经验,这当然是一个好主意,但从底部开始这样做也是有效的,这可能是最好的方法学习。

0

面向对象编程的可重用性是使用以前的类或函数或方法在本类中,但没有以前的类的问题。