0

Is it possible to override a method for a single instance? e.g.

class test
{
    protected function print()
    {
    echo "printed from old method";
    }
}

$a= new test();
can i overrride method "print" only for object $a?
e.g. $a->test=function(){echo "printed with new method";}

I know its abit weird but in my project a common class ("base") is part of many other classes each of which needs a slightly modified version of "base". I just need to override one method each time. Trying to avoid creating a huge number of subclasses of "base" for this purpose.

p.s. i have seen the solution you propose but it doesn't work for me. php version is 7.4.3

here is my code:

class nodeGroup
{
    public function test()
    {
        echo "internal";
    }
        
}

$a= new nodeGroup();
$a->test = (function() {
    echo "external";
})->bindTo($a);

$a->test();

result is "internal"
Parakmi I
  • 25
  • 6
  • 1
    Doesn't this go against OCP? – Cid Oct 10 '20 at 22:29
  • Have you considered using interfaces? – Rain Oct 10 '20 at 22:43
  • I think the right way to do this is to either make a new class that inherits from the original class and overrides the method, or use interfaces. Another option would be to add a member that is a pointer to the function you want to call and call it in the method if it is not false, otherwise, use the normal method function. I think this violates the policy of least surprise though, and trying to override a method on an instanced object most certainly does. – Justin Swanhart Oct 11 '20 at 05:14

2 Answers2

1

You could declare an anonymous class on the fly:

$a = new class extends nodeGroup {
    public function test()
    {
        echo 'external';
    }
};

$a->test();  // 'external'

Demo

Jeto
  • 14,596
  • 2
  • 32
  • 46
  • This could be the solution but the actual class has many other methods and properties that don't change and would need to be declared again in the anonymous class. – Parakmi I Oct 10 '20 at 22:40
  • 2
    @ParakmiI No they wouldn't: this anonymous class extends `nodeGroup`, therefore it inherits everything from it (except what you override explicitly). Edited the demo link with a corresponding example. – Jeto Oct 10 '20 at 22:41
  • I didn't know you can do that. Seems like a very good solution. Thank you. – Parakmi I Oct 10 '20 at 22:55
  • @ParakmiI It's available since PHP 7. Not the most common feature around, but it's got its uses. – Jeto Oct 10 '20 at 22:56
0

You could add a property to the class, and the print() method can check whether the property is set.

class test
{
    public $print_function;

    public function print()
    {
        if (isset($this->$print_function)) {
            ($this->$print_function)();
        } else {
            echo "printed from old method";
        }
    }
}

$a = new test();
$a->print_function = function() {
    echo "printed with new method";
};
$a->print();
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • This works good Thanks. However it would be usefull to know if there is a cleaner way to averride methods in an instance. Afraid there isn't.... – Parakmi I Oct 10 '20 at 22:25
  • 1
    The "clean" way to do it would be to define a subclass and use that. – Barmar Oct 10 '20 at 22:29