标签归档:抽象类

思考PHP语言四:接口和抽象类

思考PHP语言四:接口和抽象类
【概述】
在写PHP的日子里,我们多是按照需求完成相关功能,对于一些设计的工作较少的接触,也许是PHP的历史遗留问题或者其它,对于PHP的接口与抽象类使用得较少,但是对于一个支持面向对象的语言,接口与抽象是两个非常重要的内容。这里我们介绍接口与抽象类的一些基础知识,思考一些关于面向对象的东西。
【接口】
接口是一些方法特征的集合,这里的方法没有实现,只有声明。如果一个类继承了某个接口,则需要实现这个接口的所有方法。接口除了声明方法外,还可以定义常量。如下所示:

1
2
3
4
interface IFoo {
	const CONST_VAR = 'martin';
	public function method($str);
}

接口中方法的声明需要包含方法的名称,参数。不用包含参数类型和返还类型(PHP的函数本来就不用定义参数类型和返还类型)。
接口的方法只能是public,这说明接口本身包含的对外开放的意义在访问控制中体现出来了,并且当我们实现接口的方法时,也不能修改方法的访问控制权限。

接口是可以继承的,接口可以继承接口(和类继承一样,使用extends关键字),类可以继承接口(我们称之为接口继承,用implements关键字)

实现同一个接口的两个类可能功能完全不同,但是他们有相同的方法以及方法参数,并且都是公开的,从而他们可以提供相类似的服务,从而具有相同的接口。

接口的可插入性
在一个拥有多个层次结构的类组织中,如果要给某个处于中间位置的类添加父类,如果我们没有接口,则我们需要修改这个类的所有父类,打乱整个类的层次结构。当有了接口后,任何一个类都可以实现一个接口,此时,接口不会影响父类,但是会影响所有的子类,此类将必须实现这个接口的所有方法(抽象类可以不用实现所有方法,只是将实现下移到子类),子类则可以自动从此类继承实现后的方法。这就是接口的可插入性。

接口通常被用来声明一个新的类型,并且会作为一个类组织结构的起点,特别是当某个实体属于多个类型时,此时接口的作用就体现出来了。另外,理想情况下(现实中没发现过)一个类只应该实现接口或抽象类所声明的方法,纯理想呵。

【抽象类】
抽象类是类的一种,通过在类定义前添加abstract关键字实现。如下示例:

1
2
3
abstract class AbstarctFoo {
	abstract public function method();
}

抽象类不能实例化,一般作为类组织结构中枝节点或根节点存在。
抽象类提供一个类型的部分实现,抽象类可以有实例变量,可以有构造方法,可以有抽象方法,同时也可以有具体的方法实现。抽象类的构造方法可以被子类调用,只是需要显式调用。
我们在做设计时需要注意的是一般不要从具体类继承,具体类是用来实例化的。
在类的组织结构中,一般抽象类是枝节点,具体类是叶节点,在设计结构时应该尽量将公共代码放到作为父类的抽象类中,这样可以提高代码的复用性,与公共代码的移动相反,数据应该尽量放到具体类。
在继承过程中,子类的责任是扩展父类,而不是置换或取消掉父类的职责,当有取消或置换父类的职责的情况发生时,此时可能你的设计有问题了,需要考虑他们是否是is-a的关系?
抽象类和接口有相同的方法时
在PHP中,如果一个类继承了一个抽象类并且实现了一个接口,如果此时这个抽象类和接口中有相同名称的方法,则此时对于接口的实现会报错。与此相同,当一个抽象类实现一个接口时,如果接口已经声明了方法A,则在抽象方法中将不能再次声明此方法。