面向对象☞继承

类的继承

什么先理解解下什么是类的继承?类的继承就是指使用一个关键字extends将两个类或更多的类联系起来,继承类可以使用被继承类的一些属性方法进行重写或直接使用,通常我们把被继承的类叫做父类,继承类叫子类。我们先来看下一个继承案例:

面向对象☞继承

该实例表明human子类继承了jizhuidongwu父类并可以直接使用父类的$pro1属性

那么继承在面向对象中还有哪些相关概念呢?总结一下:

  • 继承:一个类从另一个已有的类中获得其特征方法称为继承
  • 派生:从一个已有的类中产生一个新的类称为派生
  • 父类/子类:已有类为父类新建类为子类。父类也叫“基类”,子类也叫“派生类”
  • 单继承:一个类只能从一个上级类继承其特性信息。PHP和大多数面向对象语言都是单继承模式,c++是多继承模式
  • 扩展:在子类中再来定义自己一些新的特有的信息(属性方法和常量)

当然这不是说父类中什么属性方法都能被子类使用?这就牵扯到访问权限的问题。

访问(权限)修饰符

在面向对象语言中主要有这三种访问修饰符:

  1. Public:公共的、共有的、公开的
  2. Protected:受保护的
  3. Privated:私有的

既然说它们是访问权限修饰符,那么肯定被修饰的属性或方法可使用位置的权限就不同,下面来看一下它们的不同

Public公有的

顾名思义,被该修饰符修饰的成员可在“任何位置“”使用(访问)。

这里任何位置指的是三种位置—也就只有这三种位置,访问位置:

  • 某个类内部:类的方法内
  • 某个类的既有继承关系的子类(父类:很少(子类可通过调用父类的函数来实现父类访问子类))的内部:是指子类的某个方法内
  • 类外部:在类括号的外面使用对象调用类中的属性

看下具体演示:

面向对象☞继承

可以明显看到受到public修饰的$p1和$p2分别可以在子类方法showInfo2内、自己类的方法内、类外使用

总结一下:就是public相当于全面公开

Protected受保护的

Protected修饰符相当于加了一把锁,不允许在类的外部使用,可以在自己类的方法内或子类的方法内使用

面向对象☞继承

可以明显看出使用D的一个对象来在类外部使用D的一个属性$p2报了语法错误,而在类方法内使用自身和父类属性都满足语法

总结一下:任何环境除了类外部

Private私有的

私有说明该类自身的属性、方法只能自身类使用且只能在类内部方法中使用

面向对象☞继承

总结:只能在自身类内部使用

最后对着三种修饰符做个总结:

范围

本类内

继承关系类内

类外

Public

可以

可以

可以

Protected

可以

可以

不可以

Private

可以

不可以

不可以

说完了继承的基本概念和访问权限问题之后,我们在编程中经常会发现有时候需要同时对父类和子类进行初始化,这时候两个构造函数就可能会引起混淆,为了实现这个机制,我们又引入了parent关键字来代表父类,同时parent也用在子类调用父类中的静态成员的时候

注意:

  • 对于方法,如果省略访问修饰符,默认按public算
  • 对于普通属性不能省略,var代表public
  • 对于静态属性,可以省略按public算
  • 对于常量,默认都是public

Parent父类

一提到parent,我们就不由得先前学过的self,$this,我们来简单的比较一下:

  1. Parent:父类类名
  2. Self:自身类名
  3. $this:该类对象

为什么必须使用parent才能满足上述讲的两个要求呢?

  1. 对父类和子类同时进行初始化:父类和子类构造方法同名,在初始化时只能调用自身的构造方法,使用self和$this都无法调用父类的构造方法
  2. 子类调用父类的静态成员:调用父类的静态成员格式:父类名::$成员名(属性或方法),获取父类名只能通过parent来实现

上面讲的是父类和子类同时都有构造方法的情况,下面看一下其他的情况:

析构方法构造方法在继承中的体现

  • 情况1:子类中没有定义构造方法时,会自动调用父类的构造方法。因此实例化子类时,需按照父类的构造方法的形式进行

面向对象☞继承

明显参数比对错误报错,修改为:

面向对象☞继承

  • 子类定义了自己的构造法方法则不会调用父类的构造方法,但可以手动调用:parent::__construct();

面向对象☞继承

调用父类的构造方法:

面向对象☞继承

  • 子类中没有定义析构方法时会自动调用父类的析构方法
  • 子类定义了自己的析构方法,则不会自动调用父类的析构方法,可通过parent::__destruct()来调用

说完了构造方法和析构方法在继承中使用时,我们不妨想一种现象,是不是父类和子类中具有相同的属性名或相同的方法名时是不是也按这种方法来处理呢?这里有一些区别,就是基本在父类和子类中相同的方法名通过子类来调用时只会使用子类中的方法,这就涉及到重写。

重写的基本要求

重写不是乱重写,比如一个protected修饰的方法在子类中重写时对应方法的控制权限应大于等于protected,也就是说

  • 重写时下级的访问控制权限应该不低于上级的访问控制权限
  1. 上级:public 下级:只能public
  2. 上级:protected 下级:protected、public
  3. 上级:private 下级:private、protected、public—实际中此情况并无意义,因为私有修饰的成员只能在自己类中使用
  • 重写方法参数数量应该一致:应该跟父类的一致

面向对象☞继承

明显参数不对需要将参数数量匹配

面向对象☞继承

更多参数也不对:

面向对象☞继承

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

面向对象☞继承

最后来讲述一些不能被继承的类和方法

最终类final class:

通常,一个类没有特别声明的话,则“别人”可以随意拿过来进行扩展—继承。但是:如果某个类不希望对其进行扩展,则可以将其声明为“最终类”

形式:

final class 类名{....类定义...}

最终方法final method:

形式:

final function 类名{....类定义...}

工厂模式:

就是指一个类:该类的作用就是“生成”各种对象,只要指定类名就可以获得一个类的对象

面向对象☞继承