gremo
gremo

Reputation: 48899

Overriding an instance method without inheritance in PHP?

Ok, i know that probably this is not possible, but i'll give it a try. Maybe my knowledge is not so good. Please don't downvote, this is just for curiosity and this maybe due to a poor OO design.

Assume that class definition for A is:

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

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

And then, without using a good and decent OO design, you create class B which is going to use fetchDataForCharting from the repository, for doing some other different calculations:

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

Sometimes you need only A, sometimes you need only B, sometimes both. Is there any way of overriding fetchData at runtime? I mean someting like $.extend() in jQuery:

$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

Upvotes: 0

Views: 2267

Answers (3)

ThiefMaster
ThiefMaster

Reputation: 318468

There is no proper way to modify/replace/add a class method.

The runkit extension has runkit_method_redefine() and runkit_method_add() but both are experimental and ugly (they take a code string, not a Closure object like your anonymous function is).

Upvotes: 1

Matthew
Matthew

Reputation: 48284

The short answer is no.

The closest you can get to exactly what you are asking is something like:

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

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

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

Requires PHP 5.4 for $this support. But keep in mind that people do that sort of thing in JavaScript because it doesn't have "real" object oriented programming. You shouldn't try to emulate JavaScript, Ruby, Python, etc, just for the sake of doing it.

To be clear: in PHP, inheritance or composition or dependency injection is probably the proper way to go about what you are trying to do. (The above hack is definitely not what you should be doing.)

Upvotes: 0

Mike Brant
Mike Brant

Reputation: 71384

It is not really clear to me what you are trying to do, but in PHP you can have calss B extend class A by writing the class B declaration as so:

Class B extends Class A {
   ...
}

You can the override the fetchData function within Class B like

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

Or

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

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

Hope this helps.

Upvotes: 0

Related Questions