9.6 类的继承与接口
继承(inheritance)是OOP中最重要的特性与概念。父类拥有其子类的公共属性和方法。子类除了拥有父类具有的公共属性和方法以外,还拥有自己独有的属性和方法。
PHP使用关键字extends来确认子类和父类,实现子类对父类的继承。
以下实例通过酒店不同类型房间之间的关系来介绍类之间的继承关系,其中还涉及接口和访问修饰符的使用,具体操作步骤如下。
【例9.4】(实例文件:ch10\9.4.php)
<html> <head> <title> 类的继承与接口</title> </head> <body> <?php class roomtypes{ public $customertype; private $hotelname="GoodHome"; protected $roomface="适合所有人"; function __construct(){ $this->customertype="everyonefit"; } function telltype(){ echo "此房间类型为".$this->customertype."。<br />"; } function hotelface(){ echo "此房间".$this->roomface."。<br />"; } final function welcomeshow(){ echo "欢迎光临".$this->hotelname."。<br />"; } } class nonviproom extends roomtypes{ function __construct(){ $this->customertype="nonvip"; } function telltype(){ echo "此".__CLASS__."房间类型为".$this->customertype."。<br />"; } function hotelface(){ echo "此房间不是".$this->roomface."。<br />"; } } class viproom extends roomtypes implements showprice{ function __construct(){ $this->customertype="vip"; } function showprice(){ if ( __CLASS__ == "superviprooms"){ echo "价格高于500元。<br />"; }else{ echo "价格低于500元。<br />"; } } } final class superviprooms implements showprice, showdetail{ function showprice(){ if ( __CLASS__ == "superviprooms"){ echo "价格高于500元。<br />"; }else{ echo "价格低于500元。<br />"; } } function showdetail(){ if ( __CLASS__ == "superviprooms"){ echo "超级vip客户可以使用会员卡取得优惠。<br />"; }else{ echo "普通客户与vip客户不能使用会员卡。<br />"; } } interface showprice{ function showprice(); } interface showdetail{ function showdetail(); } $room2046 = new roomtypes(); $room2046->telltype(); $room2046->hotelface(); $room2046->welcomeshow(); $room307 = new nonviproom(); $room307->telltype(); $room307->hotelface(); $roomv2 = new viproom(); $roomv2->telltype(); $roomv2->showprice(); $roomsuperv3 = new superviprooms(); $roomsuperv3->showprice(); $roomsuperv3->showdetail(); ?> </body> </html>
运行结果如图9-4所示。
【案例分析】
(1)类roomtypes拥有类属性$customertype、$hotelname、$roomface。类roomtypes的构造函数给类属性$customertype赋值为"everyonefit"。类方法有telltype()、hotelface()、welcomeshow()。
(2)类nonviproom使用extends关键字继承了类roomtypes。此时roomtypes为nonviproom的父类,而nonviproom为roomtypes的子类,并拥有类roomtypes的所有属性和方法。
(3)类nonviproom为了区别于roomtypes,对其所继承的属性和方法进行了“覆写”(overriding)。继承的类属性$customertype被重新赋值为"nonvip"。类方法telltype()和hotelface()被重新定义。__CLASS__变量指代当前类的名称。
(4)类viproom同样继承了类roomtypes。它们之间也形成了子类与父类的关系。同时,类viproom还通过implements关键字使用了接口(interface)showprice。类viproom重新为继承的类属性$customertype赋值为"vip",并且定义了接口函数showprice()。
(5)类superviprooms直接声明且继承了showprice和showdetail这两个接口,并且定义了接口函数showprice()和showdetail()。
(6)通过关键字interface声明接口showprice和showdetail,并且定义了接口函数showprice()和showdetail()。
(7)类roomtypes的类属性$hotelname的值为“GoodHome”,访问可见性为private。所以它的子类nonviproom和viproom都无法访问此属性。类roomtypes属性$roomface的值为“适合所有人”,访问可见性为protected。所以它的子类都可以访问。其子类nonviproom就通过hotelface()方法对此属性进行了访问。
(8)最后通过new关键字生成类实例$room2046、$room307、$roomv2、$roomsuperv3,再通过“->”直接调用实例中的类方法。
【讲解知识点】
(1)在PHP中类的继承只能是单独继承,即由一个父类(基类)继承下去,而且可以一直继承下去。PHP不支持多方继承,即不能由一个以上的父类进行继承,如类C不能同时继承类A和类B。
(2)由于PHP支持多方继承,为了对特定类的功能进行拓展,就可以使用接口来实现类似于多方继承的好处。接口用interface关键字声明,并且单独设立接口方法。
(3)一个类可以继承于一个父类,同时使用一个或多个接口。类还可以直接继承于某个特定的接口。
(4)类、类的属性和方法的访问,都可以通过访问修饰符进行控制。放在属性和类的前面则表示,public为公共属性或方法,private有自有属性或方法,protected为可继承属性或方法。
(5)关键字final放在特定的类前面,表示此类不能再被继承。final放在某个类方法前面,表示此方法不能在继承后被“覆写”或重新定义。