继承特性简化了对象和类的创建,增加了代码的可重用型。
但是PHP只支持单继承,如果想实现多继承,就需要使用接口。PHP可以实现多个接口。
接口通过关键字interface来声明。
注意:
-
接口中不能声明变量,只能使用关键字const声明为常量的成员属性。
-
接口中声明的方法必须是抽象方法。
-
接口中所有的成员都必须具有public访问权限。
语法格式:
interface 接口名称{
//常量成员
//抽象方法
}
与继承使用extends关键字不同的是,实现接口使用的是implement关键字:
class 接口类 implement 接口名称{}
- 实现接口的类必须实现接口中声明的所有方法,除非这个类被声明为抽象类。
例子:
interface Maxmin{
//这两个方法必须在子类中继承,修饰符必须为public
public function getMax(); //抽象方法
public function getMin(); //抽象方法
}
class msm implements Maxmin{ //类msm 实现 接口Maxmin
private $aa = 33;
private $bb = 66;
//具体实现接口声明的方法
public function getMax(){
return $this->bb;
}
public function getMin(){
return $this->aa;
}
//这里还可以有自己的方法
public function getOther(){
return '这里是自己的方法';
}
}
$msm = new msm();
echo $msm->getMax();
echo '<br>';
echo $msm->getMin();
echo '<br>';
echo $msm->getOther();
/*
输出:
66
33
这里是自己的方法
*/
总结
(1)在PHP中,类的继承只能单独继承,即一个子类只能有一个父类。子类又可以被继承,而且可以一直继承下去。
(2)由于PHP不支持多方继承,为了对特定类的功能进行拓展,可以利用接口(interface)来实现多方继承。接口用interface关键字声明,并且单独设置接口方法。
(3)一个子类只能有一个父类,一个子类可以有一个或多个接口,父类可以有多个子类。
(4)类、类的属性、类的方法的访问都可以通过访问修饰符进行控制。访问修饰符:public表示公共属性或方法,private表示自有属性或方法,protected表示可继承的属性或方法。
(5)关键字final类前面,表示此类不能再被继承。放在类方法前面,表示此方法不能再继承后被“覆写”或重新定义。
抽象类和接口的
相同点:
(1)不能直接通过new实例化,只能作为父类被继承。
区别:
(1)声明:抽象类由关键字abstract声明,接口由interface声明。
(2)成员方法:均为抽象方法。只声明,不实现。
抽象类的抽象方法必须用关键字abstract修饰,以分号结尾,且没有方法内容。子类必须实现抽象类的所有方法,否则会报错。
接口的方法修饰符必须为public。不能用abstract修饰,否则会报错。
接口如何继承接口?
使用extends关键字。要多个继承的话用逗号把继承的接口隔开。类实现接口时,必须实现所有相关的抽象方法。
例子:
interface test1 {
public function fruits();
}
interface test3 {
public function tool1();
}
interface test4 {
public function tool2();
}
interface test2 extends test1 { //接口继承接口
public function vegetables($p);
}
interface test5 extends test1,test3,test4 { //接口继承多个接口(全为1级继承)
public function myfunc2();
}
interface test6 extends test1,test2,test3,test4 { //接口继承多个接口(包含1级继承和2级继承)
public function myfunc3();
}
class testt1 implements test2 { //类实现接口,同时必须实现相关的抽象方法
public function fruits() {
echo "水果 <br>";
}
public function vegetables($p){
echo "蔬菜: ".$p."<br>";
}
public function myfunc1(){ //可以有自己的方法
echo "testt自己的方法 <br>";
}
}
class testt2 implements test5 {
public function fruits() {
echo "水果 <br>";
}
public function tool1(){
echo "工具1 <br>";
}
public function tool2(){
echo "工具2 <br>";
}
public function myfunc2(){ //test5的方法
echo "海 <br>";
}
}
class testt3 implements test6 {
public function fruits() {
echo "水果 <br>";
}
public function vegetables($p){
echo "蔬菜: ".$p."<br>";
}
public function tool1(){
echo "工具1 <br>";
}
public function tool2(){
echo "工具2 <br>";
}
public function myfunc3(){ //test6的方法
echo "盐 <br>";
}
}
//类的实例化(单接口继承)
$aaa = new testt1();
$aaa -> fruits();
$aaa -> vegetables("西红柿");
$aaa -> myfunc1();
/*输出:
水果
蔬菜: 西红柿
testt自己的方法
*/
//类的实例化(多接口继承-1级)
$bbb = new testt2();
$bbb -> fruits();
$bbb -> tool1();
$bbb -> tool2();
$bbb -> myfunc2();
/*输出:
水果
工具1
工具2
海
*/
//类的实例化(多接口继承-1级和2级)
$ccc = new testt3();
$ccc -> fruits();
$ccc -> vegetables("咚咚咚");
$ccc -> tool1();
$ccc -> tool2();
$ccc -> myfunc3();
/*输出:
水果
蔬菜: 咚咚咚
工具1
工具2
盐
*/
例子:
//接口的成员方法可以有内容吗?答:不能
interface Fruits{
//这两个方法必须在子类中继承,修饰符必须为public
public function getName(); //因为没有内容,所以是抽象的
// public function getPrice(){ //报错:不能包含body。结论:在interface中所有的方法都是public abstract的,即使你没有声明它是public abstract的.
// }
//接口的抽象方法可以用abstract修饰吗?答:不能
// public abstract function getDDe(); //Fatal error: Access type for interface method Fruits::getDDe() must be omitted
//接口的方法可以不用public修饰吗?答:可以,应该默认就是公共的
function getDDe();
}
class apples implements Fruits{
private $aa = 'apple';
private $bb = 8;
//具体实现接口声明的方法
public function getName(){
return $this->bb;
}
public function getDDe(){
return $this->aa;
}
//这里还可以有自己的方法
public function getNum(){
return '购买数量';
}
}
$app = new apples();
echo $app->getName();
echo '<br>';
echo $app->getDDe();
echo '<br>';
echo $app->getNum();
例子:
//一个子类如何实现多个接口?
interface test1 {
public function fruits();
}
interface test3 {
public function tool1();
}
interface test4 {
public function tool2();
}
class testt4 implements test1,test3,test4 {
public function fruits() {
echo "水果 <br>";
}
public function tool1(){
echo "工具1 <br>";
}
public function tool2(){
echo "工具2 <br>";
}
}
$ddd = new testt4();
$ddd -> fruits();
$ddd -> tool1();
$ddd -> tool2();
/*输出:
水果
工具1
工具2
*/
例子:
//抽象类可以继承抽象类吗?
//抽象类继承另一个抽象类时,不能重写抽象父类的抽象方法。--可以理解为对抽象类的扩展。
abstract class abc1 {
protected $e = 0;
abstract function fruits();
abstract function vegetables($e);
}
abstract class abc2 extends abc1 {
//abstract function fruits(); //重写报错
abstract function funct(); //自己的方法
}
class abc3 extends abc2 {
function fruits(){
echo "水果 <br>";
}
function vegetables($e){
echo "蔬菜:".$e."<br>";
}
function funct(){
echo "东东 <br>";
}
public function tool(){ //自己的方法
echo "工具 <br>";
}
}
$eee = new abc3();
$eee -> fruits();
$eee -> vegetables("土豆");
$eee -> funct();
$eee -> tool();
/*输出
水果
蔬菜:土豆
东东
工具
*/
例子:
interface Fruits{
public function getName(); //因为没有内容,所以是抽象的
//接口的方法可以不用public修饰吗?答:可以,应该默认就是公共的
function getDDe();
}
class apples implements Fruits{
private $aa = 'apple';
private $bb = 8;
//具体实现接口声明的方法
public function getName(){
return $this->bb;
}
public function getDDe(){
return $this->aa;
}
//这里还可以有自己的方法
public function getNum(){
return '购买数量';
}
}
$app = new apples();
echo $app->getName();
echo '<br>';
echo $app->getDDe();
echo '<br>';
echo $app->getNum();
/*输出:
8
apple
购买数量
*/