search

Home  >  Q&A  >  body text

php - 框架中是如何调用子类方法的?

很多框架都提供了前置后后置操作,比如__init()方法,会在__construct()后首先被调用。

YII2中会有beforeFind(),afterFind()。

这些都是自定义方法,比如在UserModel,但是UserModel extends Model

我发现这些方法的调用都是在Model这个父类中调用的,为什么父类能调用子类的方法?

还是通过其他方法调用的?

补充一下:

框架中类似的__init()、beforeFind(),afterFind()等等这些前置后置方法,是如何被调用的。

PHPzPHPz2902 days ago176

reply all(3)I'll reply

  • 怪我咯

    怪我咯2017-04-10 17:11:51

    后期静态绑定

    不知道是不是你需要的东西,用于静态方法的。

    PHP:后期静态绑定

    reply
    0
  • PHPz

    PHPz2017-04-10 17:11:51

    没太明白你的意思, 我想父类在定义的时候都不知道会有什么子类方法,怎么可能会调用子类的方法。
    你说的自定义方法是重写的父类的方法还是完全属于子类的方法,
    好纠结O.O
    贴下代码吧

    我明白你的意思了。
    我没有安装YII2 ,我找了下TP的相同功能函数,比如说控制器的初始化方法_initialize。其实在实例化控制器类的时候在__construct中就有调用

    /**
         * 架构函数 取得模板对象实例
         * @access public
         */
        public function __construct() {
            Hook::listen('action_begin',$this->config);
            //实例化视图类
            $this->view     = Think::instance('Think\View');
            //控制器初始化
            if(method_exists($this,'_initialize'))
                $this->_initialize();
        }

    这是TP的控制器基类中的代码,调用了_initialize 大概你的意思是为什么就调用了子类的这个初始化方法吧。
    子类对于public修饰的方法和成员变量都是可以继承的。
    你实例化子类的时候调用肯定是子类重写的方法,如果没有重写,就调用从父类继承过来的方法。这里不是父类调用的,而是子类调用的
    你可以测试下。

    class MyParent
    {
        function __construct(){
            if(method_exists($this, 'test')){
                $this->test();
            }
        }
        function test(){
            echo "this is parent's test\n";
        }
    }
    class MyChild extends MyParent
    {
        function test(){
            echo "this is child's test\n";
        }
    }
    
    $object1 = new MyChild();
    $object2 = new MyParent();

    个人的理解哈。O.O

    reply
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-10 17:11:51

    你其实弄错了,理解错了继承的概念。

    eg:

    <?php
    
    class Model {
        function doThings() {
            $this->doFirstThing();
            $this->doSecondThing();
            $this->doThirdThing();        
        }
    }
    
    class UserModel extends  Model {
    
        function doFirstThing() {
            printf('第 1 件事情'."\n");
        }
        
        function doSecondThing() {
            printf('第 2 件事情'."\n");
        }
        
        function doThirdThing() {
            printf('第 3 件事情'."\n");
        }
    }
    
    $user = new UserModel();
    $user->doThings();
    
    $model = new Model();
    $model->doThings();

    父类 Model 在 doThings 方法中确实调用了子类 UserModel 的方法。

    但真是这样子吗?不是!

    UserModel 继承自 Model,因此 UserModel 拥有父类所有的可继承属性和方法,因此,UserModel 也拥有自己的 doThings 方法,只是与父类中的代码一模一样而已。

    所以,UserModel 完整的是这样的:

    class UserModel extends  Model {
        
        function doThings() {
            $this->doFirstThing();
            $this->doSecondThing();
            $this->doThirdThing();        
        }
        function doFirstThing() {
            printf('第 1 件事情'."\n");
        }
        
        function doSecondThing() {
            printf('第 2 件事情'."\n");
        }
        
        function doThirdThing() {
            printf('第 3 件事情'."\n");
        }
    }

    只是,子类继承了父类的方法后,如果你不打算重写它,就没必要显示的写出来了,如果需要修改,就写出来,然后做修改,比如我们要修改顺序:

    function doThings() {
        $this->doThirdThing();            
        $this->doSecondThing();
        $this->doFirstThing();
    }

    所以说哈,不能看见代码写在父类了,就认为是父类调用的,其实是子类调用的。

    当然,如果你要说,哎呀,我有时候想用自己重写(override)的,比如上面的 3、2、1 顺序,有时候想用父类的 1、2、3顺序,该怎么办呢。

    parent::doThings();

    这里的 parent 也只是说,这里调用时使用父类中的代码块。调用着本身,其实仍然是 UserModel

    reply
    0
  • Cancelreply