PHP:如何重用代码(oop)?

Fat*_*per 4 php oop

我已经学习了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;
    }
} 
Run Code Online (Sandbox Code Playgroud)

我可以理解代码,但不确定为什么它可以重用.每次我想在iTemplate界面中添加新功能时,我的Template类也需要更改.我不理解"重用"的概念.我感谢任何帮助.谢谢.

irc*_*ell 8

接口不直接用于代码重用.它们用于抽象.它们允许使用模板的类检查接口而不是基本模板类.这样它将实现与接口声明分开.

因此,如果您的方法对template类执行某些操作,则检查实例对象template将难以编写对该类的依赖关系.但实际上你并不关心你得到什么课程,你只关心它是否坚持iTemplate界面(因为你无论如何都是这样).

public function foo(Template $template) {
Run Code Online (Sandbox Code Playgroud)

VS:

public function foo(iTemplate $template) {
Run Code Online (Sandbox Code Playgroud)

现在,就代码重用而言,接口并不是真的为此而设计的.通常是继承.基本上认为继承是扩展抽象.让我给你举个例子:

如果你要为鸟类创建一组类,你可以用继承方法来处理它,没有它.让我们看看如何在没有:

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
    }
}  
Run Code Online (Sandbox Code Playgroud)

现在,这是一个简单的例子,但你可以看到,在这两只鸟中,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!');
    }
}  
Run Code Online (Sandbox Code Playgroud)

现在,你可以看到我们只是重复使用了3种方法!我们没有声明speak(),因为它总是被覆盖(因为没有两只鸟听起来相似).

听起来不错吧?那么,根据我们的需要,我们可能想要添加其他抽象类型.所以我们假设我们制作了许多不同类型的鸟......我们会有一些不会游泳的东西,所以我们可能会创建一个NonSwimmingBird扩展的抽象类Bird,但会为我们抛出异常.或者a NonFlyingBird或者ShortRangeBird......

现在,就代码重复使用而言,我们确实在轨道上,但我们正在另一个领域碰壁.假设我们有一只不会飞或游泳的鸟.我们从哪个班继承?无论哪种方式,我们都在复制代码.所以我们需要找到另一条出路.那么,我们怎么做呢?通过设计模式 ...我们可以使用装饰器模式动态添加这些特征,而不是直接继承.(这里可以使用其他模式,重点是表明继承本身并不适合所有需求.而模式本身也不会.你需要一个基于你的确切需求的两个世界的良好架构) ...

关键是,这一切都取决于您的需求.如果你只有2个"类"的对象,那么你将要构建一些比你计划拥有数千个更简单的东西.我在这里写的内容是演示如何使用直接继承强制执行某些DRY主体(以及直接继承如何导致代码重复).最重要的是,不要因为你不想重复自己而坚持干.坚持干,但要确保你合并并延伸到合理的地方,否则你会让自己陷入困境.坚持单一责任校长,你应该没事......