跳至正文

php class 之继承篇

  • 后端

  很多时候,我们定义了一些对象以后,在使用的时候会发现,某个方法不太适用目前的某个要求了,但是由于这个方法在其他地方多次使用,我们又不能修改这个方法,如果再新建一个 class 的话,其余的方法又都重复了,这个时候我们就可以使用 class 间的继承了,继承就像儿子继承父亲的财产一样,子对象可以直接使用父对象的方法,也可以重写父对象的方法,我们先看一个简单的例子:

class man {
    public $height = 180;
    public function getHeight(){
        echo "I'm father,my height is :".$this->height;
        echo "<br>";
    }
    public function la(){
        echo "啦啦啦<br>";
    }
}

class son extends man{
    public $height = 120;
    public function getHeight(){
        echo "I'm son,my height is :".$this->height;
        echo "<br>";
    }
}

$man = new man();
$son = new son();
$man->getHeight();//调用父对象自己本身的方法
$son->getHeight();//调用子对象自己本身的方法
$son->la();//调用父对象方法

  我们定义了一个 man 对象。然后又定义了一个 son 对象,son 使用 extends 关键字 继承了 man,表示 son 是 man 的子对象。需要注意的是,一个父对象可以有多个子对象,我们可以写很多个对象来继承 man。但是子对象只能有一个父对象,这个就不解释了。

  下面的执行的代码,前四行我们都不多解释了,最后一行$son->la();我们 son 对象里并没有定义 la() 这个方法,但是依然可以输出,这也就是继承特点,子对象可以直接调用父对象的方法。其实子对象也可以直接调用父对象的属性,比如我们删除了 son 里面 height 的定义,然后在执行,依然可以输出,只不过输出的身高变成了父对象设置的高度属性。简单点来说,就相当于,如果子对象自己有,就优先用自己的,自己没有就用父对象的,如果父对象也没有,就继续找父对象的父对象,依次类推。如果都找不到则报错。

  子对象也可以定义一些和父对象无关的方法去使用。就是子对象和父对象的方法不要求完全一致
当子对象重写父对象方法的时候,参数列表也必须要一致,简单说就是个数要一致,除了构造函数以外,父方法有几个参数,对应的子方法也要有几个参数。

  需要特别说明的是,一个类的私有方法或者变量是 private 类型的时候,子类是不能直接使用的。比如:

class man {
    private $height = 180;
    public function getHeight(){
        echo "I'm father,my height is :".$this->height;
        echo "<br>";
    }
}
class son extends man{
    public function getHeight(){
        echo "I'm son,my height is :".$this->height;
        echo "<br>";
    }
}
$son = new son();
$son->getHeight();

  我们给man定义了一个私有变量 $height,在 son 里面并没有定义 $height,然后我们试图使用$son->getHeight();的时候,就会报错。

  class 还有一种变量类型。在前面我们并没有介绍,放到这里介绍比较合适,关键字:protected 意思就是受保护的类型,这种类型只能本身和子对象才可以调用,其他地方则不能调用,比如:

class man {
    protected $height = 180;
    public function getHeight(){
        echo "I'm father,my height is :".$this->height;
        echo "<br>";
    }
}
class son extends man{
    public  function getHeight(){
        echo "I'm son,my height is :".$this->height;
        echo "<br>";
    }
}
$man = new man();
$son = new son();
$man->getHeight();
$son->getHeight();

  我们定义了一个 protected 类型的变量,然后在子类里面使用,发现可以正常使用,而当我们试图在外部直接赋值的时候$son->height = 120;则会报错提示我们找不到 height 这个属性。而把 height 改成 public 以后,则可以正常赋值。
静态方法和变量的继承,几乎和非静态的差不多,只需要注意一下保持都是静态的就行了,这里就不过多介绍了,喜欢动手的朋友可以自己试一下,也许会发现什么惊喜。下面我们再介绍几个关于 class 的知识点。

parent:
使用 parent 关键字,字对象可以访问父对象被字对象覆盖的方法,具体使用形式是parent::functionname();比如

class man {
    protected $height = 180;
    public function getHeight(){
        echo "I'm father,my height is :".$this->height;
        echo "<br>";
    }
}
class son extends man{
    protected $height = 120;
    public function getHeight(){
        echo "I'm son,my height is :".$this->height;
        echo "<br>";
        parent::getHeight();
    }
    
}
$man = new man();
$son = new son();
$man->getHeight();
$son->getHeight();

在子方法里面使用parent::getHeight();调用已经被覆盖的 getHeight 方法。执行结果如下:

I'm father,my height is :180
I'm son,my height is :120
I'm father,my height is :120

  看到这里,就会感觉很奇怪了,为什么最后输出的是 120?这里就是 class 的一些处理机制问题了,我们知道子对象可以覆盖父对象的 public 和 protected 类型的属性和方法。在 php 处理的过程中 ,父对象的属性,是完全被覆盖的,相当于消失了,所以最后才会输出 120, 而私有的属性则不会被覆盖,使用 parent 的时候,则会继续使用父对象的属性,我们再简单的看一个例子:

class man {
    public $height = 180;
    protected $weight = 65;
    private $sex = "男";
    public function getData(){
        echo "I'm father,height:$this->height,weight:$this->weight,sex:$this->sex<br/>";
    }
}

class daughter extends man{
    public $height = 120;
    protected $weight = 45;
    public $sex = "女";
    public function getData(){
        echo "I'm daughter,height:$this->height,weight:$this->weight,sex:$this->sex<br/>";
        parent::getData();
    }
    
}

$daughter = new daughter();
$daughter->getData();

输出结果为:

I'm daughter,height:120,weight:45,sex:女
I'm father,height:120,weight:45,sex:男

  我们很明显的可以看到,身高和体重,父对象里面调用的时候,都被子对象覆盖了,而性别是私有属性,子对象无法覆盖,所以性别输出还是男。class 允许继承的时候修改属性的类型,但是只能范围变得更大,而不能变小,比如 private 可以修改为 public,反之则不行。

final:
父对象声明的 final 类型的方法,不允许子对象覆盖,否则会报错。

相关文章

php class 之入门篇

php class 之静态篇