在PHP中覆盖没有继承的实例方法?

时间:2012-07-16 22:01:04

标签: php

好的,我知道这可能是不可能的,但我会试一试。也许我的知识不太好。请不要downvote,这只是为了好奇,这可能是由于糟糕的OO设计。

假设A的类定义是:

class A
{
    public function build()
    {
        $data = $this->fetchData();
        ...
    }

    public function fetchData()
    {
        // Database eavy query
        return $this->repository->fetchDataForCharting();
    }
}

然后,在没有使用良好和体面的OO设计的情况下,您创建了将从存储库中使用B的类fetchDataForCharting,以进行其他一些不同的计算:

class B
{
    public $data;

    public function getMonthlyLimit()
    {
        // Database eavy query
        $data = $this->getData();
    }

    public function getData()
    {
        return isset($this->data) ? $this->data :
            $this->repository->fetchDataForCharting();
    }
}

有时您只需要A,有时您只需要B,有时两者都需要。有没有办法在运行时覆盖fetchData?我的意思是像jQuery中的$.extend()一样:

$b = new B();
$b->getMonthlyLimit(); // $b->data filled

$a = new A();

// Override fetchData
$a = extend($a, 'fetchData', function() use($b) { return $b->data; });

$a->build(); // Just 1 query

3 个答案:

答案 0 :(得分:1)

没有正确的方法来修改/替换/添加类方法。

runkit扩展程序有runkit_method_redefine()runkit_method_add(),但两者都是实验性的和丑陋的(它们采用代码字符串,而不是像匿名函数一样的Closure对象)。

答案 1 :(得分:0)

我真的不清楚你要做什么,但在PHP中你可以通过编写B类声明来使calss B扩展A类:

Class B extends Class A {
   ...
}

您可以覆盖B类中的fetchData函数,如

public function fetchData {
    // do something different than in class A
}

或者

public function fetchData {
    // execute the Class A functionality first
    parent::fetchData();

    // now do something in addition to what is in Class A functionality
}

希望这有帮助。

答案 2 :(得分:0)

简短的回答是否定的。

你能得到的最接近的是:

class A
{
  public function __construct()
  {
    $this->bar = function()
    {
    };
  }

  public function foo()
  {
    $bar = $this->bar;
    $bar();
  }
}

$a = new A();
$a->bar = function()
{
  // override
};
$a->foo();

需要PHP 5.4才能获得$this支持。但请记住,人们在JavaScript中做这种事情是因为它没有“真正的”面向对象编程。你不应该试图模仿JavaScript,Ruby,Python等,只是为了做到这一点。

要明确:在PHP中,继承或组合或依赖注入可能是你正在尝试做什么的正确方法。 (上面的黑客肯定是你应该做什么。)