第七章:第9节 PHP面向对象——重写

更新于:2020-12-10 10:11:53

重写override

重写又叫覆盖,就是将从父类继承下来的属性或方法重新“定义”——就是重新写。


前面楠神讲过:


A类继承了B类,会把B类的一些属性和方法继承过来,都有哪些属性和方法会被继承?子类没有同名的属性和方法,并且访问修饰符不是private的会被继承下来。


我们现在重新理解这句话:


A类继承了B类,会把B类的一些属性和方法继承过来,都有哪些属性和方法会被继承?访问修饰符不是private的会被继承下来,但B类属性和方法会被A类同名的属性和方法覆盖掉。


重写的概念不难理解,重写的一些基本要求:


访问控制权限

下级的访问控制权限应该不低于上级的访问控制权限:

上级:public  下级:只能public

上级:protected  下级: protected, public

上级:private   下级:private  protected  public——实际此情况无意义。

私有的不能覆盖,而是完全当作自己全新的。


1.png

1.png

 

方法的参数形式

应该跟父类的一致。少了不行,多了也不行。


1.png

1.png


额外说明:


私有属性和私有方法的重写问题:私有属性和方法都不能覆盖,但其实子类可以定义跟父类私有的同名属性或方法。只是当作一个自身的新的属性或方法来看待而已。不过方法的参数必须一致。


构造方法的重写问题:构造方法不但可以像其他普通方法一样重写,而且,比普通方法更宽松:重写的时候参数可以不一致,访问控制权限可以低于父级的访问控制权限


重点:


看如下的代码:

class Father {// 父类
    private $num = 10;
    public function showFather() {
       echo $this->num;
    }
}
class Son extends Father { //子类
    public function showSon() {
       echo $this->num;
    }  
}
$son = new Son();
$son->showFather(); 
$son->showSon();


运行结果是这样的:


1.png


说明:


子类调用showFather方法,showFather方法是父类的公开方法,子类可以继承,在这种情况下,子类是可以通过父类的showFather方法获取到父类的私有属性$num的。


子类调用showSon方法,由于showSon方法是子类自己的方法,而父类的成员属性$num是私有的,子类无法继承,所以子类没有$num成员变量,showSon方法获取$num成员变量失败报错。


再看下面几种情况:


子类父类同时有成员变量$num,修饰符不一样,最终获取的值是怎么样的:

class Father {// 父类
    private $num = 10;
    public function showFather() {
       echo $this->num;
    }
}
class Son extends Father { //子类
    private $num = 20;
    public function showSon() {
       echo $this->num;
    }  
}
$son = new Son();
$son->showFather(); 
echo '<br />';
$son->showSon();


1.png

现象①:父类子类成员变量都私有,子类对象调用父类方法获取的是父类成员变量,子类方法获取的是子类成员变量


class Father {// 父类
    private $num = 10;
    public function showFather() {
       echo $this->num;
    }
}
class Son extends Father { //子类
    protected $num = 20;
    public function showSon() {
       echo $this->num;
    }  
}
$son = new Son();
$son->showFather(); 
echo '<br />';
$son->showSon();

1.png

现象②:父类成员变量私有、子类成员变量非私有,子类对象调用父类方法获取的是父类成员变量,子类方法获取的是子类成员变量


class Father {// 父类
    protected $num = 10;
    public function showFather() {
       echo $this->num;
    }
}
class Son extends Father { //子类
    protected $num = 20;
    public function showSon() {
       echo $this->num;
    }  
}
$son = new Son();
$son->showFather(); 
echo '<br />';
$son->showSon();

1.png

现象③:父类子类成员变量都非私有,子类对象调用父类方法、子类方法都获取的是子类成员变量


class Father {// 父类
    public function showFather() {
       echo $this->num;
    }
}
class Son extends Father { //子类
    private $num = 20;
    public function showSon() {
       echo $this->num;
    }  
}
$son = new Son();
$son->showFather(); 
echo '<br />';
$son->showSon();

1.png


现象④:父类没有成员变量,子类成员变量私有,子类对象调用父类方法访问子类私有成员变量会报错


class Father {// 父类
    public function showFather() {
       echo $this->num;
    }
}
class Son extends Father { //子类
    protected $num = 20;
    public function showSon() {
       echo $this->num;
    }  
}
$son = new Son();
$son->showFather(); 
echo '<br />';
$son->showSon();

1.png

现象⑤:父类没有成员变量,子类成员变量非私有,子类对象调用父类方法是可以访问到子类的非私有成员变量的。


总结:


子类对象调用自己的方法访问成员变量

如果子类有成员变量,就访问子类自己的;

如果子类没有成员变量,可继承父类的就访问父类的。


子类对象调用父类的方法访问成员变量

子类没有则访问父类的成员变量;

父类没有则访问子类的非私有成员变量;

子类父类都有成员变量,父类成员变量私有,访问的是父类的。父类成员变量非私有,访问的是子类的。


成员变量$num 改成 成员方法num() 效果是一样的。

把子类、父类的 shou方法 改成 静态方法 来调用,效果也是一样的。


本节学习代码》》》