AccessControlandInheritance[TOC]本文验证分析得到的结论是类内的调用不受访问控制约束的限制。类之间的调用受访问控制约束的限制。只有public修饰的成员才能在类外访问。即实例化对象只能直接访问public修饰的成员。(注:类中声明魔术方法__get()时,实例化对象访问类的未定义成员或私有成员是间接访问。)子类和父类中同时定义同名方法时间。父类中的同名方法用private修饰,子类中的同名方法与父类中的同名方法不构成覆盖关系。并且①如果父类中有其他public方法调用了这个同名方法②子类没有重写调用同名方法的public方法,那么子类的实例化对象访问这个public方法,并且公共方法仍然调用父类方法的同名方法。(另一篇文章参考:继承自父类的函数中的$this仍然指向php中的父对象?)子类与父类中的同名方法构成Overriding(覆盖)关系,但要求子类同名方法的访问修饰符作用域>=子类同名方法的访问修饰符作用域子类同名,否则会报致命错误。一般的代码编辑器也会提示。$this是一个伪变量,表示对调用对象的引用。在类定义中调用方法时使用$this。__CLASS__魔法常量,代表当前类。功能同get_class()。要获取调用对象所属类的类名,请使用get_called_class()函数或get_class($this)。当访问控制类中的成员(属性或类常量或方法)没有被任何访问修饰符修饰时,默认被public修饰。访问控制修饰作用域是否参与继承public当前类内部、子类内部、当前类外部、子类外部YESprotected在当前类内部、子类内部YESprivate只能在当前类内部访问NO注意:只参与在继承(通过公共或受保护)中,成员方法可以被覆盖(overridden)。因为private修饰的私有方法对子类是不可见的,也就是说几乎可以认为私有方法不参与继承***。另外,php中的(overload)重载并不是真的像其他语言(比如java)中描述的那种概念。PHP重载。示例代码下面的代码写在一个名为base.php的文件中,并在PHP8上运行。name=$name;$this->性别=$性别;$this->birth=$birth;$this->telephone=$telephone;}//私有方法私有函数printHello(){echo__CLASS__.'你好'。PHP_EOL;}//声明一个公共方法并调用上面的私有方法printHellopublicfunctionprintTest(){$this->printHello();}}classchildextendsSuper{//声明一个与父类中的私有方法printHello同名的公共方法printHello,看是否构成对父类中同名方法的重写privatefunctionprintHello(){echo“Avantidelittledonkey”;}}$init=['Erika','Female','2003-08-12','158xxxx0812'];$super=newSuper(...$init);$child=newchild(...$在里面);echo$super->printTest();echo$child->printTest();运行上面的代码,结果输出:[Running]php"base.php"SuperhelloSuperhello[Done]exitedwithcode=0in0.086seconds重点分析简化上面的代码,重点分析子类继承父类的public或protected方法,调用父类的private方法,然后在子类中声明同名的private方法,$this引题第一种情况:子类直接继承父类,子类没有实现里面的任何方法。printHello();}}classchildextendsSuper{}$super=newSuper();echo$super->printTest();echo'------------------------------------'.PHP_EOL;$child=newchild();echo$child->printTest();输出结果如下。从输出结果我们知道,子类继承了父类的所有方法,包括超级私有方法printHello()。显然这不符合我们的预期,因为在其他强类型面向对象语言中,私有修饰的方法被描述为不可继承。这里我们可以先想到这是php底层实现造成的,暂时先不管,差不多就认为在php中,私有方法是不能继承的。这里有疑问的同学可以先参考这篇文章,探索PHP核心:继承、多态和抽象类。基于这种考虑,我认为子类中只有一个公共方法printTest()。在类外,Child的实例化对象$child调用printTest()时,Child中没有可访问的printHello()方法。,发出致命错误。但是,它与我的预期不符。$child->printTest()时,printTest()里面的$this->printHello()访问的是父类的私有方法printHello(),此时的$this是对$child对象的引用。这不禁让人疑惑,子类实例化对象的引用$this怎么访问父类的私有方法呢?这不科学。string(5)"Super"array(2){[0]=>string(10)"printHello"[1]=>string(9)"printTest"}超级你好----------------------------------字符串(5)“子”数组(2){[0]=>字符串(10)“printHello”[1]=>string(9)"printTest"}childhello第二种情况:子类声明了一个与父类的私有方法同名的printHello()方法。注意:此方法与父类中的printHello()不重叠。写关系。printHello();}}classchildextendsSuper{publicfunctionprintHello(){echo"Avantidelittledonkey";}}$super=newSuper();echo$super->printTest();echo'-----------------------------------'.PHP_EOL;$child=newchild();echo$child->printTest();结果输出如下。从结果可以看出,$child->printTest()时,此时的$this是对$child对象的引用,printTest()内部的$this->printHello()仍然访问私有方法printHello(),而不是在子类中声明的printHello()。这让人们更加疑惑了。string(5)"Super"array(2){[0]=>string(10)"printHello"[1]=>string(9)"printTest"}超级你好----------------------------------字符串(5)“子”数组(2){[0]=>字符串(10)“printHello”[1]=>string(9)"printTest"}childhello第三种情况:子类重写了父类的公有方法printTest(),但函数体不变。printHello();}}classchildextendsSuper{publicfunctionprintTest(){$this->printHello();}}结果输出如下。这时候的结果和预期的一样,$child->printTest()是致命错误。因为在Child中没有可访问的printHello()方法。可即便如此,与第一种情况相比,又出现了新的疑点?子类中重写的printTest()与继承的printTest()在实现上是一样的。为什么第一段代码不报错,而现在的代码会报错,是因为继承的printTest()和重写的printTest()在内存中存放的位置不同吗?string(5)"Super"array(2){[0]=>string(10)"printHello"[1]=>string(9)"printTest"}超级你好----------------------------------致命错误:未捕获错误:从第26行的上下文“child”调用私有方法Super::printHello()错误:CalltoprivatemethodSuper::printHello()fromcontext'child'情况4:子类声明了一个与父类的私有方法同名的printHello()方法,子类重写了父类的公共方法printTest(),但函数体保持不变。printHello();}}classchildextendsSuper{publicfunctionprintHello(){echo"Avantidelittledonkey";}//声明一个公共方法,调用上面的私有方法printHellopublicfunctionprintTest(){$this->printHello();}}$super=newSuper();echo$super->printTest();echo'---------------------------------'.PHP_EOL;$child=newchild();echo$child->printTest();此时结果输出如下。我认为这种情况是最毋庸置疑和意料之中的。string(5)"Super"array(2){[0]=>string(10)"printHello"[1]=>string(9)"printTest"}超级你好----------------------------------AvantideLittleDonkey这个问题已经在我在这个网站上发起的问答中得到了回答$thisinPHPProblemsraisedwheninheriting?参考文章:PHP继承相关的一个问题PHP静态绑定和动态绑定静态绑定和动态绑定的区别PHP面向对象动态绑定和静态绑定的理解
