草庐IT

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

coder 2024-04-29 原文

我学过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 界面中添加一个新功能时,我的模板类也需要更改。我不明白“重用”的概念。我感谢任何帮助。谢谢。

最佳答案

接口(interface)不直接用于代码重用。它们是为了抽象。它们使使用模板的类能够检查接口(interface)而不是基模板类。这样它将实现与接口(interface)声明分开。

因此,如果您的方法对 template 类执行某些操作,检查实例 template 的对象将硬编码对该类的依赖。但实际上你并不关心你得到的是什么类,你只关心它是否遵循 iTemplate 接口(interface)(因为无论如何你都在调用它)。

public function foo(Template $template) {

对比:

public function foo(iTemplate $template) {

现在,就代码重用而言,接口(interface)并不是真正为此而设计的。继承通常是。基本上将继承视为扩展抽象。让我举个例子:

如果您要为鸟类创建一组类,您可以使用继承来处理它,也可以不使用它。让我们看看如果没有:

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,但会为我们抛出异常。或 NonFlyingBird,或 ShortRangeBird...

现在,就代码重用而言,我们确实走上正轨,但我们在另一个领域碰壁了。假设我们有一只既不会飞也不会游的鸟。我们从哪个类继承?无论哪种方式,我们都在复制代码。所以我们需要另谋出路。那么,我们该怎么做呢?通过Design Patterns ...我们可以使用装饰器模式动态添加这些特征,而不是直接继承。 (这里还有其他模式可以使用,关键是要表明仅继承并不能满足所有需求。而且模式本身也不会。您需要​​根据您的确切需求使用两个世界的良好架构) ...

重点是,这完全取决于您的需求。如果您只有 2 个“类”的对象,那么与计划拥有数千个对象相比,您将要构建一些更简单的东西。我在这里写的重点是演示如何使用直接继承来强制执行某些 DRY 原则(以及直接继承如何导致代码重复)。最重要的是,不要因为不想重复自己而试图坚持 DRY。坚持 DRY,但要确保在合理的地方进行组合和扩展,否则会给自己带来维护上的麻烦。坚持Single Responsibility Principal ,你应该没问题...

关于PHP:如何重用代码(oop)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3702248/

有关PHP:如何重用代码(oop)?的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  4. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  5. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  6. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  7. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  8. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  9. ruby-on-rails - Rails 源代码 : initialize hash in a weird way? - 2

    在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has

  10. ruby - 如何每月在 Heroku 运行一次 Scheduler 插件? - 2

    在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/

随机推荐