<?php
class pa{
    private function m(){
        echo 'Parent\'s function';
    }
    public function run(){
        $this->m();
    }
}
class child extends pa{
    public function m(){
        echo 'child\'s function';
    }
}
$obj=new child();
$obj->run();你们猜,结果是什么,居然是parents function,可是,m()方法没有被继承因为protected,run()集成到了子类,那么方法里面的this应该指向子类实例,调用子类m方法,结果却调用了,父类的m方法,如果把private改成public,则调用子类方法m,谁能解释一下

解决方案 »

  1.   

    没有找到更详细的解释extends作用机理的文章,以下只是我的猜测我觉得造成这种问题的原因可能在于,虽然表面上是继承了父类,但是父类实际上是存在的,也就是说,如果通过子类的实例化对象来调用父类中的某个方法,那么实际上它进入到了父类的空间里,那么在父类空间里的$this的作用范围就是父类空间本身,而不能跨越到子类的空间中。之所以会这么猜想,是因为PHP的变量的引用原理,也就是当一个变量的值,是另一个变量的引用时,并不等同于这两个变量变成了同一个变量,其实本身还是两个变量,并且销毁其中一个的时候,另一个仍然存在。所以基于此我认为,子类的实例化对象不应该使用父类中的$this来代表子类的对象,这样会造成对象的“越级”
      

  2.   


    public  和  private结果是不一样的,当属性变为public,this就代表子类,能解释吗
      

  3.   

    如果父类是Class A,子类是Class B,个人觉得内存结构应该是这样A = Class AB = { (继承自Class A) Class B } <-- $this子类对象创建的时候,应该是先创建了父类对象,然后父类的内存块作为子类内存块的一部分(子类=父类内存结构+子类自有)所以父类中的定义的this调用的方法要么是父类的方法,要么是父类中被子类重写的。你的子类实例中没有定义run方法,访问的就是父类的公共方法run,此时$this应该已经是指向父类了,所以$this->m()调用的就是父类中未被重写的私有m方法B = { (继承自Class A) <-- $this Class B } 比如下面这里例子<?php
    class pa{
        public function a(){
            $this->sd();  // $this指向父类,而父类中未定义sd方法,子类的sd方法又是私有的,所以没有输出,子类的sd改成public即可输出。
        }
    }
    class child extends pa{
        public function m(){
            $this->a();
        }    private function sd(){
            echo 'sd';
        }
    }
    $obj=new child();
    $obj->m();没有深入理解过php的内部实现,欢迎指导讨论。
      

  4.   


    没明白,怎么解释public 和 private结果不同
      

  5.   

    private 私有的,只能被自己访问。不会被继承和覆盖
    public 共有的,可任意访问、继承、覆盖
      

  6.   


    没明白,怎么解释public 和 private结果不同因为对于php来说 public 和 private 是2种不同的修饰也就是说,当父类是private m时,子类的public m其实只是子类的内部方法,而和父类完全没有关系,当调用run时,首先回去run声明的空间寻找private的方法,如果找到,则直接执行,否则回去当前对象的空间寻找public或者protected的方法,如果还没有找到,并且有extends class 则会去class的空间找,仍然没有的话,则会报错。
      

  7.   


    public  和  private结果是不一样的,当属性变为public,this就代表子类,能解释吗按照上面各位大大的解释,private是不能被覆盖的,而public可以被覆盖,所以你改为public之后,就是父类的方法被子类覆盖了
      

  8.   


    没明白,怎么解释public 和 private结果不同因为对于php来说 public 和 private 是2种不同的修饰也就是说,当父类是private m时,子类的public m其实只是子类的内部方法,而和父类完全没有关系,当调用run时,首先回去run声明的空间寻找private的方法,如果找到,则直接执行,否则回去当前对象的空间寻找public或者protected的方法,如果还没有找到,并且有extends class 则会去class的空间找,仍然没有的话,则会报错。run()方法已经是子类的方法了,那么$child->run()执行的就是子类自己的方法,run()里面的this也是出现在子类中,指代子类对象,那么$this->m()调用的因该是子类的m()而不是父类的m(),我这么理解的。子类和父类的m()没关系,这点我在帖子中已经说了m()没被继承,我的问题是run()方法里面的this指向,为什么在private和public情况下不同,谢谢
      

  9.   


    public  和  private结果是不一样的,当属性变为public,this就代表子类,能解释吗按照上面各位大大的解释,private是不能被覆盖的,而public可以被覆盖,所以你改为public之后,就是父类的方法被子类覆盖了
    那与this的指向有什么关系?
      

  10.   


    没明白,怎么解释public 和 private结果不同因为对于php来说 public 和 private 是2种不同的修饰也就是说,当父类是private m时,子类的public m其实只是子类的内部方法,而和父类完全没有关系,当调用run时,首先回去run声明的空间寻找private的方法,如果找到,则直接执行,否则回去当前对象的空间寻找public或者protected的方法,如果还没有找到,并且有extends class 则会去class的空间找,仍然没有的话,则会报错。run()方法已经是子类的方法了,那么$child->run()执行的就是子类自己的方法,run()里面的this也是出现在子类中,指代子类对象,那么$this->m()调用的因该是子类的m()而不是父类的m(),我这么理解的。子类和父类的m()没关系,这点我在帖子中已经说了m()没被继承,我的问题是run()方法里面的this指向,为什么在private和public情况下不同,谢谢run()啥时候是子类方法了,你run是定义在父类里的啊。它的public表示它可以被子类访问和重写,不代表它就直接属于子类的方法啊。$child->run()执行时$child实例里是没有run方法的。所以按照8楼所说,因为child是子类,所以在子类中找不到时到父类空间中找,这时父类中的run方法中的$this就是表示父类本身。你使用$this->m()时,由于$this目前表示父类,而m()又是private的,所以不存在被覆盖的可能,子类里定义的是属于子类自己的,跟父类无关。调用的就是父类的m,而不是子类。当你把父类的m()的private改成public,父类的m()就存在被重写的可能,所以程序会去继承他的子类中去寻找(也就是你的$child),如果找到则调用子类的,没找到调用父类自己的m()
      

  11.   

    第一种请看等价于:<?php
    class child{
        private function m(){
            echo 'Parent\'s function';
        }
        public function run(){
            $this->m();
        }
        public function m(){
            echo 'child\'s function';
        }
    }$obj=new child();
    $obj->run();
    这样搞也可以吗?
      

  12.   

    $this 是类实例化后的对象
    所以 $this 指向的是对象,而不是类
    实例化后,无论是基类还是继承类的方法都在对象中
    具体执行的是哪个方法由 php 根据规则决定
    class pa{
      private function m(){
        echo __METHOD__ . ' Parent\'s function';
      }
      public function run(){
        echo __CLASS__ . ' ';
        $this->m();
      }
    }
    class child extends pa{
      public function m(){
       echo __METHOD__ . ' child\'s function';
      }
    }
    $obj=new child();
    $obj->run();得到 pa pa::m Parent's function
    pa::m 方法是私有的,不可被覆盖class pa{
      public function m(){
        echo __METHOD__ . ' Parent\'s function';
      }
      public function run(){
        echo __CLASS__ . ' ';
        $this->m();
      }
    }
    class child extends pa{
      public function m(){
       echo __METHOD__ . ' child\'s function';
      }
    }
    $obj=new child();
    $obj->run();得到 pa child::m child's function
    pa::m 方法是公有的,可以被覆盖class pa{
      private function m(){
        echo __METHOD__ . ' Parent\'s function';
      }
      public function run(){
        echo __CLASS__ . ' ';
        $this->m();
      }
    }
    class child extends pa{
      public function m(){
       echo __METHOD__ . ' child\'s function';
      }
      public function run(){
        echo __CLASS__ . ' ';
        $this->m();
        parent::run();
      }
    }
    $obj=new child();
    $obj->run();得到
    child child::m child's function
    pa pa::m Parent's function不能理解就慢慢理解吧。规矩不会因为你而改变
    我就偏要再“答非所问”一回!
      

  13.   


    没明白,怎么解释public 和 private结果不同因为对于php来说 public 和 private 是2种不同的修饰也就是说,当父类是private m时,子类的public m其实只是子类的内部方法,而和父类完全没有关系,当调用run时,首先回去run声明的空间寻找private的方法,如果找到,则直接执行,否则回去当前对象的空间寻找public或者protected的方法,如果还没有找到,并且有extends class 则会去class的空间找,仍然没有的话,则会报错。run()方法已经是子类的方法了,那么$child->run()执行的就是子类自己的方法,run()里面的this也是出现在子类中,指代子类对象,那么$this->m()调用的因该是子类的m()而不是父类的m(),我这么理解的。子类和父类的m()没关系,这点我在帖子中已经说了m()没被继承,我的问题是run()方法里面的this指向,为什么在private和public情况下不同,谢谢run()啥时候是子类方法了,你run是定义在父类里的啊。它的public表示它可以被子类访问和重写,不代表它就直接属于子类的方法啊。$child->run()执行时$child实例里是没有run方法的。所以按照8楼所说,因为child是子类,所以在子类中找不到时到父类空间中找,这时父类中的run方法中的$this就是表示父类本身。你使用$this->m()时,由于$this目前表示父类,而m()又是private的,所以不存在被覆盖的可能,子类里定义的是属于子类自己的,跟父类无关。调用的就是父类的m,而不是子类。当你把父类的m()的private改成public,父类的m()就存在被重写的可能,所以程序会去继承他的子类中去寻找(也就是你的$child),如果找到则调用子类的,没找到调用父类自己的m()这时父类中的run方法中的$this就是表示父类本身。按这么说,你的理论就是,实力化子类的时候,父类也实例化了?this只能引用对象不能引用类,你的意思是创建子类的时候,顺便把父类实例化了?否则this这个东西就是个矛盾,都不存在父类对象,哪存在this
      

  14.   

    $this 是实例化后的对象
    就像 $obj=new child(); 后的 $obj 一样
    如果你是在对象内部访问对象的方法和属性的话,总不能老是要把 $obj 传进去吧?
    所以就有了 $this 这个载体其实所有面向对象的语言中都有这个 this,也的确迷糊了众多的初学者。其实没有什么好不理解的
    this 就是对象自己
      

  15.   

    所以,版主的意思是,子类实例化前,父类也必须先实例化,否则存在在父类中的this没有父类对象供引用,这是第一段代码的结论。
    但是根据第二段代码,父类run里面的this调用了子类对象的方法,所以结论,this指向子类,和第一段代码矛盾this到底指向父类还是子类对象
    那么,父类方法中的this,到底引用的是父类,还是子类对象?(难道存在父类对象),根据php代码的运行结果,明显矛盾,一会指向父类一会指向子类
      

  16.   


    你说的这个我明白,我真正不明白的地方是,子类继承父类方法function a()(这个方法a()内用到了this),这个继承过来的this,到底是谁的this?13楼的回答看得出来他明白了我是什么意思,但是解释的有矛盾,而版主还是没理解我的意思,我不是不明白private和this的规则,我市不知道在继承过程中,this传到了子类的过程中,指向发生了改变还是怎么回事,你的前2个代码的运行结果,明显是php运行机制中的矛盾点
      

  17.   

    再重复一遍:this 就是对象自己
      

  18.   

    既然这样,那么继承过来的子类应该等同于下面把
    class child extends pa{
        public function m(){
            echo 'child\'s function';
        }
    public function run(){//只继承了run(),m()私有,没继承
            $this->m();
        }
    }
    那么this就是指向这个类(child)的对象,可是他用了一个不存在的m()方法
      

  19.   


    没明白,怎么解释public 和 private结果不同因为对于php来说 public 和 private 是2种不同的修饰也就是说,当父类是private m时,子类的public m其实只是子类的内部方法,而和父类完全没有关系,当调用run时,首先回去run声明的空间寻找private的方法,如果找到,则直接执行,否则回去当前对象的空间寻找public或者protected的方法,如果还没有找到,并且有extends class 则会去class的空间找,仍然没有的话,则会报错。run()方法已经是子类的方法了,那么$child->run()执行的就是子类自己的方法,run()里面的this也是出现在子类中,指代子类对象,那么$this->m()调用的因该是子类的m()而不是父类的m(),我这么理解的。子类和父类的m()没关系,这点我在帖子中已经说了m()没被继承,我的问题是run()方法里面的this指向,为什么在private和public情况下不同,谢谢
    最后回复一帖,不想在这个问题多做纠结了首先,看下面这个例子
    <?php
    class pa{
        private function m(){
            echo 'Parent\'s function';
        }
    }
    class child extends pa{
        public function run(){
            if(is_callable($this, 'm')) {
    echo 'private function can callable';
    } else {
    echo 'private function can not callable';
    }
        }
    }
    $obj=new child();if(method_exists($obj, 'm')) {
    echo 'private function can extends';
    } else {
    echo 'private function can not extends';
    }$obj->run();
    接着再看
    <?phpfunction print_method($obj) {
    $refObj = new ReflectionObject($obj); foreach($refObj->getMethods() as $refFun) {
    echo "Define class name : ", $refFun->getDeclaringClass()->getName(), "\n";
    echo "Modifiers for method ", $refFun->name,":\n";
    echo $refFun->getModifiers() . "\n";
    echo implode(' ', Reflection::getModifierNames($refFun->getModifiers())) . "\n";
    }
    } class pa{
        private function m(){
            echo 'Parent\'s function';
        }
        public function run(){
            print_method($this);
    // 从上面的输出可以看到,$this = $obj,
    // 这里隐含一个输出,为什么会隐藏,这就是继承的关系,我们知道public和protected会被子类同名给覆盖
    // 但是private又会被保护,不能覆盖,那么其实就是有2份m,一个private m,另外一个就是子类 public m
    $this->m();
    // 而这里的m调用时,会找那个m调用呢?
    // 很简单,就是优先找当前method所定义class处的private,因为有了private就不用考虑继承覆盖的问题

        }
    protected
    }
    class child extends pa{
        public function m(){
            echo 'child\'s function';
        }
    }
    $obj=new child();print_method($obj);$obj->run();但愿你能明白。