PHP 面向对象程序设计(oop)学习笔记(一) - 抽象类、对象接口、instanceof 和契约式编程
1、PHP中的抽象类
PHP5支持抽象类和抽象方法。定义为抽象的类不能被实例化。任何一个类,如果它里面至少有一个方法是被声明为抽象的,那么这个类就必须被声明为抽象的。被定义为抽象的方法只是声明了其调用方式(参数),不能定义其具体的功能实现。在类的声明中使用abstract修饰符可以将某个类声明为抽象的。
可以这样理解,抽象类作为一个基类,它把特定的细节留给继承者来实现。通过抽象概念,可以在开发项目中创建扩展性很好的架构。
abstractclassAbstractClass
{
code...
}
1.1、抽象方法
使用abstract关键字定义抽象方法。抽象方法只保留方法原型(方法的定义中剔除了方法体之后的签名),它包括存取级别、函数关键字、函数名称和参数。他不包含({})或者括号内部的任何代码。例如下面的代码就是一个抽象方法定义:
abstractpublicfunctionprototypeName($protoParam);
继承一个抽象类的时候,子类必须定义父类中的所有抽象方法;另外,这些方法的访问控制必须和父类中一样(或者更为宽松)。此外方法的调用方式必须匹配,即类型和所需参数数量必须一致。
1.2、关于抽象类
某个类只要包含至少一个抽象方法就必须声明为抽象类
声明为抽象的方法,在实现的时候必须包含相同的或者更低的访问级别。
不能使用new关键字创建抽象类的实例。
被声明为抽象的方法不能包含函数体。
如果将扩展的类也声明为抽象类,在扩展抽象类时,可以不用实现所有的抽象方法。(如果某个类从抽象类继承,当它没有实现基类中所声明的所有抽象方法时,它就必须也被声明为抽象的。)
1.3、使用抽象类
<?php
abstractclassCar
{
abstractfunctiongetMaxSpeend();
}
classRoadsterextendsCar
{
public$Speend;
publicfunctionSetSpeend($speend=0)
{
$this->Speend=$speend;
}
publicfunctiongetMaxSpeend()
{
return$this->Speend;
}
}
classStreet
{
public$Cars;
public$SpeendLimit;
function__construct($speendLimit=200)
{
$this->SpeendLimit=$speendLimit;
$this->Cars=array();
}
protectedfunctionIsStreetLegal($car)
{
if($car->getMaxSpeend()<$this->SpeendLimit)
{
returntrue;
}
else
{
returnfalse;
}
}
publicfunctionAddCar($car)
{
if($this->IsStreetLegal($car))
{
echo'TheCarwasallowedontheroad.';
$this->Cars[]=$car;
}
else
{
echo'TheCaristoofastandwasnotallowedontheroad.';
}
}
}
$Porsche911=newRoadster();
$Porsche911->SetSpeend(340);
$FuWaiStreet=newStreet(80);
$FuWaiStreet->AddCar($Porsche911);
/**
*
*@result
*
*TheCaristoofastandwasnotallowedontheroad.[Finishedin0.1s]
*
*/
?>
2.对象接口
使用接口(interface),可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。
接口是通过interface关键字来定义的,就像定义一个标准的类一样,但其中定义所有的方法都是空的。
接口中定义的所有方法都必须是公有,这是接口的特性。
接口是一种类似于类的结构,可用于声明实现类所必须声明的方法。例如,接口通常用来声明API,而不用定义如何实现这个API。
大多数开发人员选择在接口名称前加上大写字母I作为前缀,以便在代码和生成的文档中将其与类区别开来。
2.1接口实现(implements)
要实现一个接口,使用implements操作符(继承抽象类需要使用extends关键字不同),类中必须实现接口中定义的所有方法,否则会报一个致命错误。类可以实现多个接口,用逗号来分隔多个接口的名称。
实现多个接口时,接口中的方法不能有重名。
接口也可以继承,通过使用extends操作符。
类要实现接口,必须使用和接口中所定义的方法完全一致的方式。否则会导致致命错误。
接口中也可以定义常量。接口常量和类常量的使用完全相同,但是不能被子类或子接口所覆盖。
2.2使用接口的案例
<?php
abstractclassCar
{
abstractfunctionSetSpeend($speend=0);
}
interfaceISpeendInfo
{
functionGetMaxSpeend();
}
classRoadsterextendsCarimplementsISpeendInfo
{
public$Speend;
publicfunctionSetSpeend($speend=0)
{
$this->Speend=$speend;
}
publicfunctiongetMaxSpeend()
{
return$this->Speend;
}
}
classStreet
{
public$Cars;
public$SpeendLimit;
function__construct($speendLimit=200)
{
$this->SpeendLimit=$speendLimit;
$this->Cars=array();
}
protectedfunctionIsStreetLegal($car)
{
if($car->getMaxSpeend()<$this->SpeendLimit)
{
returntrue;
}
else
{
returnfalse;
}
}
publicfunctionAddCar($car)
{
if($this->IsStreetLegal($car))
{
echo'TheCarwasallowedontheroad.';
$this->Cars[]=$car;
}
else
{
echo'TheCaristoofastandwasnotallowedontheroad.';
}
}
}
$Porsche911=newRoadster(); $Porsche911->SetSpeend(340); $FuWaiStreet=newStreet(80); $FuWaiStreet->AddCar($Porsche911); /** * *@result * *TheCaristoofastandwasnotallowedontheroad.[Finishedin0.1s] * */ ?>