2021年9月

当前有这么一个关系

   <?php
    class A{
    }
    class B extends A{
    }

php不能直接支持重载(可以通过什么__call等奇技淫巧实现,这里不做讨论),在子类可以重写方法和属性,子类一旦有和父类名字的属性或者方法就是在重写,总结了下面的几点:
1、子类在重写子类和父类属性/方法的时候,类型要一样,父类是static的属性/方法,子类就应该是static属性/方法,父类是普通属性/方法,子类就应该是普通的属性/方法。
2、子类的权限应该小于等于父类的,父类是public function foo(){},你子类一定不能是 private/protected,只能是public function foo(){}
3、下面这几个例子,可以总结一点

class A{
    public function test(){
         echo $this->name;
    }
}
class B extends A{
    public $name = 666;
}
$m = new B();
$m->test();
//输出 666

class A{
    private $name = 777;
    public function test(){
         echo $this->name;
    }
}
class B extends A{
    public $name = 666;
}
$m = new B();
$m->test();
//输出 777

class A{
    public $name = 777;
    public function test(){
         echo $this->name;
    }
}
class B extends A{
    public $name = 666;
}
$m = new B();
$m->test();
//输出666

第一个例子感觉效果和延时静态绑定差不多,第二个例子中父类的属性是private 没有被重写,所以test()方法中就直接访问了自己的name属性 结果是 777,第三个例子中因为父类name被重写成666了,所以输出666。如果子类有个一模一样的test方法呢?输出什么,毫无疑问,应该是666。

class A{
    public $name = 777;
    public function test(){
         echo $this->name;
    }
}
class B extends A{
    public $name = 666;
    public function test(){
         echo $this->name;
    }
}
$m = new B();
$m->test();
//输出666

刚才提到延时静态绑定,简单说就是父类中的static和self关键字的区别,父类中的self关键字后面的属性/方法一定是调用的父类自己的,static关键字后面的属性/方法调用的是子类的。self其实就是当前类名,和直接写当前类名效果一样,例如下面:

class A{
    public static $name = 777;
    public static function test(){
         echo A::$name;
         echo '<br/>';
         echo self::$name;
         echo '<br/>';
         echo B::$name;
         echo '<br/>';
         echo static::$name;
    }
}
class B extends A{
    public static $name = 666;
}
$m = new B();
B::test();
// 输出
// 777<br/>777<br/>666<br/>666

<?php

class MyClass
{
    public static  function  say($a,$b){
        echo  "静态方法" . $a ."和" .$b ;
   }
    public function  speak($a,$b){
        echo  "普通方法". $a ."和" .$b ;
    }
}
   //静态方法
call_user_func_array(['MyClass','say'],[1,2]);
  //普通方法
call_user_func_array([(new MyClass()),'speak'],[1,2]);