第七章:第7节 PHP面向对象——类的继承、类的范围解析操作符

更新于:2018-11-21 14:04:17

万事万物皆对象,我们可以把“某一个人”实例化一个Person类的对象。往大了说人也是动物,也可以把“某一个人”实例化一个Animal类的对象。往小了说人又可以分为男人、女人,可以把“某一个人”实例化一个Man类或Woman类的对象。


Animal类:

1.png


Person类:

1.png


一个人既可以实例化为Animal类的对象,也可以实例化为Person类的对象,但这两个类的属性和方法不一样,实例化哪个都不能很丰富地描述一个人,是否能把这两个类的属性和方法加起来全写到一个新类里面,比如叫NewPerson类?——可以这样写,但这不是良好的编程习惯,犯了“重复造轮子”的坏毛病。明明有两个类就可以实现的功能,非得多写出一半的代码。我们重写了NewPerson类,可以把Person类的代码删掉,但把Animal类的代码也删掉就不合适了,不光是人可以实例化Animal类的对象,一只鸟也可以实例化Animal类的对象。显然重写一个NewPerson类不合适,会与Animal类产生重复代码。


写代码讲究的是模块化,不管是类、函数,最好是能像一块一块简单的积木一样,相互搭配写出复杂的功能。不要把一个类、函数写到特别臃肿,这样容易在项目中出现大量重复代码,即延长了开发时间,容易出错,还不好后期维护。


针对这个问题,最佳解决方案是什么呢?那就是让Person类去继承Animal类,不用重复写代码,就能轻松实现一个“NewPerson类”。


继承的语法 A类继承B类:

class A extends B{}


1.png


Person类继承Animal类,针对Person类来说,Animal类是它的父类;针对Animal类来说,Person类是它的子类。


1.png


引入文件时注意下,要先引入Animal类的文件,有父才有子嘛。


1.png

代码运行成功,看第9行代码,Person类没有eat方法,但它继承了Animal类的eat方法,所以能正常执行。


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


Person类和Animal类都有构造方法,Person类不会继承Animal类的构造方法,除非是把Person类的构造方法去掉。


1.png

1.png

看对象变量$p1,“男”本来是赋值给Person类的$sex属性的,因为我们注释掉了Person类的构造方法,执行的却是Animal类的构造方法,所以“男”被当成了Animal类的$feature的属性打印出来了。


构造方法在new时就调用,是类里面比较特殊且重要的一个方法。有时候子类有构造方法,并且又不想抛弃掉父类的构造方法,怎么做可以继承父类的构造方法呢。看代码:


1.png

看第14行代码,用“parent::”(也可以用Animal::)把Animal类的构造方法继承下来了,并且还能执行Person类的构造方法。


1.png

用这种方式继承被子类覆盖的父类一般方法通样有效。(覆盖指的就是子类有与父类同名的,没有继承下来的方法)


手册里的示例:

1.png

范围解析操作符(::)

范围解析操作符(也可称作 Paamayim Nekudotayim)或者更简单地说是一对冒号,可以用于访问静态成员、方法和常量,还可以用于覆盖类中的成员和方法。


我们已经多次用到这个操作符了,总结一下它共有几种使用方式和场合。


一、类名::


当在类的外部访问静态成员、方法和常量时,必须使用这种方式。


二、self::


在类内部使用,self引用的是当前类的作用域,例如A类的self指的就是A


三、parent::


在类内部使用,parent引用的是父类的作用域,例如A类继承B类,A类的parent指的就是B


四、static::


也是在类内部使用,static引用的是全部静态作用域。看下面这个例子就好理解了:


14ce36d3d539b6005574d31eea50352ac75cb7e5.jpg


static后期静态绑定特性,可以让父类去访问子类的类常量、静态属性、静态方法。


可见static在PHP的代码中有3个不同含义的语法:


函数中的静态变量:

function  f1(){
    static $v1 = 1;
}

类中的静态成员:

class A{
    static  $v1 = 1;
    static  function f1(){}
}

方法中的动态指代“当前类”:

class A{
    function f1(){
        static::f2();//static此时指代调用f1这个方法的类(或对象的类)
        self::f2(); //self这里永远指代当前A这个类。
    }
}


注意:PHP是单继承的,一个子类只能继承一个父类,需要继承多个类怎么办?那只能是让父类再去继承它的父类(爷爷类),让父类的父类(爷爷类)再去继承父类的父类的父类(太爷爷类)……


相当于一个人只能有一个父亲,可以有很多祖先。


PHP和大多数面向对象的语言都是单继承模式,C++是多继承。


本节学习代码》》》