【问题标题】:Method Chaining and Class Inheritance方法链和类继承
【发布时间】:2014-01-14 11:44:31
【问题描述】:

我想我或多或少地掌握了 OOP/继承,以及我认为我理解的方法链接的基础知识。但是我仍然对如何实际使用其中一些感到困惑。

我想做一些我以前与 Magento 合作时见过的事情: 在 Magento 中,我看到了在方法链接中使用的某种“选择器函数”。这有点难以用语言表达,但大致是这样的:

$categoryName = Mage::getModel('catalog/category')->load($categoryId)->getName();

我感兴趣的是load($categoryId) 部分,例如,一个选择某事物的某个实例并允许我在该特定实例上运行函数的函数。

现在,我正在编写一个模块,允许我在我们的网站上配置某些促销活动。鉴于我们将有许多不同的促销活动,并且我希望它们易于配置和修改,我想做类似的事情。

所以,如果我想做这样的事情:

$prm = new Promotion();

$prm->addPromo('xmasPromo');
$prm->addPromo('nyPromo');

$prm->getPromo('xmasPromo')->setName('Promotion for Xmas!');
$prm->getPromo('nyPromo')->setName('Promotion for New Years!');

echo $prm->getPromo('xmasPromo')->getName(); // returns: Promotion for Xmas!
echo $prm->getPromo('nyPromo')->getName(); // returns: Promotion for New Years!

它的类定义应该是什么样子的?

这可能比我预期的要简单或复杂得多。无论哪种情况,非常感谢!


编辑: 所以我用 deceze 给我的信息做了一些测试,但我仍然很困惑。 错误的命名并将 2 个类放在 1 个文件中,这就是我所做的:

类文件:

class Promotion {
    private $__arr = array();
    public function addPromo($name) {
        $this->__arr[$name] = new Promo();
    }
    public function getPromo($name) {
        $this->__arr[$name];
    }
}

class Promo {
    private $name;
    public function setName($name) {
        $this->name = $name;
    }
    public function getName() {
        return $name;
    }
}

和运行文件:

require_once 'class.php';
error_reporting(E_ALL);

$prm = new Promotion();

$prm->addPromo('xmasPromo');
$prm->addPromo('nyPromo');

$prm->getPromo('xmasPromo')->setName('Promotion for Xmas!');
$prm->getPromo('nyPromo')->setName('Promotion for New Years!');

echo 'X: '.$prm->getPromo('xmasPromo')->getName(); // returns: Promotion for Xmas!
echo "\n";
echo 'N: '.$prm->getPromo('nyPromo')->getName(); // returns: Promotion for New Years!

这给了我Fatal error: Call to a member function setName() on a non-object in /var/www/test/index.php on line 11。 但为什么? getPromo() 不应该把对象还给我吗? 再次感谢..


感谢这里的好人,它现在可以工作了。如果有人遇到相同或类似的问题,这里是最终的工作代码:

类:

class Promotion {
    private $__arr = array();
    public function addPromo($name) {
        $this->__arr[$name] = new Promo();
    }
    public function getPromo($name) {
        return $this->__arr[$name];
    }
}

class Promo {
    private $name;
    public function setName($name) {
        $this->name = $name;
    }
    public function getName() {
        return $this->name;
    }
}

测试文件:

require_once 'class.php';
error_reporting(E_ALL);

$prm = new Promotion();

$prm->addPromo('xmasPromo');
$prm->addPromo('nyPromo');

$prm->getPromo('xmasPromo')->setName('Promotion for Xmas!');
$prm->getPromo('nyPromo')->setName('Promotion for New Years!');

echo 'X: '.$prm->getPromo('xmasPromo')->getName(); // returns: Promotion for Xmas!
echo "\n";
echo 'N: '.$prm->getPromo('nyPromo')->getName(); // returns: Promotion for New Years!

【问题讨论】:

  • PHP method chaining?的可能重复
  • 这被称为fluent interface - 所以方法将返回自我实例。从某种意义上说,这是一种反模式
  • 实际上我可以看到的问题是,您应该从getPromo 方法返回PROMO 实例,例如return $this->__arr[$name];
  • deceze 领先你一两分钟。你当然是完全正确的,我只是太盲目了,看不到我忘记了。 :)

标签: php oop inheritance method-chaining


【解决方案1】:

方法链非常简单,它所做的只是使用 PHP 语法的一个特定元素:

当一个函数返回一个对象时,你可以直接在该函数后面继续->

速记版本可以是:

$bar = $foo->bar();
$baz = $bar->baz();
echo $baz;

$foo->bar() 返回一个对象 ($bar),它有一个方法 baz(),该方法返回一些值 ($baz)。这可以写成这样的简写:

echo $foo->bar()->baz();

$foo->bar() 仍然返回一个具有baz() 方法的对象,因此您可以直接调用它而无需将其分配给中间变量。也许这让它更明显:

echo ( $foo->bar() )->baz();

无论$foo->bar() 返回什么,您都会调用baz() 方法。

$prm->getPromo('xmasPromo')->setName('Promotion for Xmas!');

因此,在上述情况下,您需要做的就是从getPromo 返回一个具有setName 方法的对象。我会假设getPromo 应该返回一些对象,比如Promo 类。如果Promo 类有一个方法setName,那么你就准备好了。

【讨论】:

  • 嗨。感谢您的回答。拥有“Promotion”类和“Promo”类(具有 setName 和 getName 方法)很容易。但是如何使“Promotion”类中的 addPromo 和 getPromo 函数创建或分别获取 Promo 对象的适当实例?
  • 我不知道,这取决于你。当您调用addPromo 时,Promotion 类会创建一个新的Promo 对象(顺便说一句,不好命名)并将其存储在内部某个给定名称的位置。当您调用getPromo 时,它会检索该对象。可以像数组一样简单,也可以像数据库查询一样复杂。在这里你真正想做什么是你的决定。
  • 感谢我们的帮助。我用数组尝试过,但我似乎仍然无法掌握它。见原帖。
  • 也许是因为你没有returning 值?!
  • 天啊。我怎么会这么瞎。也忘了在getName 中$this。现在工作。这回答了我的问题,我真的帮助我理解了这个概念。非常感谢!
【解决方案2】:

如果你想链接方法,你只需要总是像这样返回对象

class Chain {
    public function firstChain() {
         //do something
         return $this;
    }

    public function secondChain() {
          //do some stuff

          return $this;
    }

}

当你有一个类的实例时,你会这样做:

$obj = new Chain();

$obj->fistChain()->secondChain();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-02-04
    • 2012-11-14
    • 1970-01-01
    • 2011-03-03
    • 1970-01-01
    • 1970-01-01
    • 2012-04-25
    • 2013-09-06
    相关资源
    最近更新 更多