PHP OOP类和函数

时间:2017-09-20 13:17:19

标签: php oop

我不知道如何命名,但在这里。让我们假设我有以下

class A {
    public function aa() {
       $this->bb();
    }
    public function bb() {

    }
}

class B extends a {

}

class C {
   __construct(B $service) {
       $this->service = $service;
   }
   public function aa() {

       $this->service->aa();
   }
}

我在代码中的电话将是

$C = new C(new B());
$C->aa();

所以这基本上会执行A:aa()这就是我想要的。如您所见,在A::aa() AA::bb()中被调用。

我需要什么。当调用AA :: bb()时,我想执行C类中定义的一些代码,但我不允许更改A类。我只能改变B类或C类。

我的想法是在B类中添加一个监听器并像这样覆盖bb()函数

class B extends a {
    public $listener;
    bb() {
       parent::bb();
       $this->listener();
    }
}

class C {
   __construct(B $service) {
       $this->service = $service;
   }
   public function aa() {

       $this->service->listener = function() { }
       $this->service->aa();
   }
}

但我不喜欢这个想法,看起来不是一个好主意。我有什么选择?

同样,我不能改变A类,我只能调用C类。

PHP版本是5.3

2 个答案:

答案 0 :(得分:1)

您有两种选择。延伸或装饰。

首先,你会写一些内容,但我不会对听众使用public可见性:

class Foo extends A {
    private $listener;
    public function setListener(callable $func) {
        $this->listener = $func;
    }
    public function bb() {
        call_user_func($this->listener);
        return parent:bb();
    }
}

在示例中,我通过setter注入传递了侦听器,但您也可以使用构造函数注入并在重载的$listened方法中传递__construct()。扩展类时,“接口限制”不适用于构造函数的签名。

另一种方法是使用装饰器:

class Foo {
    private $target;
    public function __construct(A $target) {
        $this->target = $target;
    }

    public function bb($callback) {
        $callback();
        return $this->target->bb();
    }

    public function __call($method, $arguments) {
        return call_user_func_array( 
                array( $this->target, $method ),
                $arguments
            );
    }
}

第二种方法可以让你改变界面。

您选择哪个选项取决于您实际需要实现的确切功能。当您需要对对象行为进行大幅度更改时,装饰器是一种解决方案 - 例如,它非常适合添加访问控制。

答案 1 :(得分:1)

我了解您希望在C中的代码完成后在A中执行代码。你无法改变A.

正如所写,C::aa调用A::aa,调用A::bb并且堆栈展开。为什么不在服务调用结束后在C::aa中完成工作?

class C {
   public function aa() {
       $this->service->aa();
       // whatever you want to do
   }
}

另一方面,如果您需要在调用A::aa之后调用代码,但在调用 A::bb之前调用,那么您发布的示例就足够清晰了:< / p>

class B extends a {
    public $listener;
    public function bb() {
       call_user_func($this->listener);
       parent::bb();
    }
}

请注意使用call_user_func,这是PHP 5.3调用存储在成员变量中的匿名函数所必需的。