在PHP中,多态是最常用到的一种特性。所谓多态,是指同一个东西不同形态的展示。在PHP中,我们这样定义多态,一个类被多个子类继承,如果这个类的某个方法在多个子类中表现不同的功能,那么这种行为我们就称其为多态的实现。

多态的实现必须要满足三个条件

  1. 子类继承父类
  2. 子类重写父类的方法
  3. 父类引用指向子类对象

到这里我们需要引入一个概念:抽象类。

抽象类中只定义(或部分实现)子类需要的方法。子类可以继承它并且通过实现其中的抽象方法,使抽象类具体化 。

  1. 抽象类至少要有一个抽象方法声明关键字 abstract
  2. 抽象类必须要有抽象方法,方法中没有大括号(函数体)
  3. 抽象方法只是声明了其调用方式(参数),不实现具体的功能,由子类实现抽象类中所有的方法
  4. 如果抽象方法有参数,那么子类的实现也必须有相同的参数个数
  5. 抽象类不能被实例化,它的意义在于被扩展
<?php
abstract class MyAbsClass
{
    abstract public function func();
    //抽象类必须要有一个抽象的方法,含有抽象方法的类也必须是抽象类
    //定义一个抽象方法之后,在定义其他的属性和方法和普通的类方式一样
    public $name = 'lilei';
    public $age = 13;
    public function test(){
        echo 'hello world';
    }
}

class ChildClass extends MyAbsClass
{
    public function func(){
        echo $this->name;
    }
    //类也可以继承抽象类,但是必须同时实现抽象类的方法,之后才可以进行类的实例化
}
class MyClass extends MyAbsClass
{
    public function func(){
        echo $this->age;
    }
    //类也可以继承抽象类,但是必须同时实现抽象类的方法,之后才可以进行类的实例化
}

abstract class SonClass extends MyAbsClass
{
    //抽象类可以继承另一个抽象类
}
$obj1 = new ChildClass();
$obj1->func();
$ojb2 = new SonClass();
$ojb2->func();

修饰关键字顺序

  1. 类的属性和方法必须添加访问修饰符(public、private和protected)
  2. abstract 以及 final 必须声明在访问修饰符之前
  3. static 必须声明在访问修饰符之后

接口

接口的意义所在,即定义一些通用的方法,好多类都同时实现这些方法,但是实现的方法不一样。接口中定义的所有方法,实现接口的类中必须全部实现,不能实现其中几个,只能全部实现,下面程序中的checkWork方法是判断某个对象是否实现了一个接口。

  1. 使用接口(interface),可以指定某个类的必须实现哪些方法,但不需要定义这些方法的具体内容,接口中也可以定义常量。
  2. 接口关键字 interface 接口里面不能有方法的具体定义和变量属性,只能是声明了方法名称和常量。
  3. 实现关键字 implements 一个类可以实现多个接口,接口也可以继承 关键字 extends

TIPS

  1. 接口里定义的方法都是抽象方法,只有方法名称,没有方法体,不需要加抽象关键字 abstract。
  2. 实现多个接口时,接口中的方法不能有重名。
  3. 接口也可以继承,通过使用 extends 操作符
  4. 类要实现接口,必须使用和接口中所定义的方法完全一致的方式。否则会导致致命错误。
  5. 定义的方法都是public公有的类型

类型运算符

  1. instanceof 用于确定一个PHP变量是否属于某一类class的实例
  2. instanceof也可以用于确定一个变量是不是继承自某一父类的子类的实例
  3. instanceof也可以用于确定一个变量是不是实现了某个接口的类的实例
<?php
interface Work
{
    public function worker($job);
}

//Programmer类实现了Work接口
class Programmer implements Work
{
    public function worker($job){
        echo 'The programmer is ' . $job . '<br/>';
   }
}

// ProductManager类也实现了Work接口
class ProductManager implements Work {
    public function worker($job){
        echo 'The product manager is ' . $job;
    }
}

// 不同的类可以实现同一个接口
$coding = new Programmer();
$coding->worker("coding");
$holiday = new ProductManager();
$holiday->worker("play game");

// 实现了某个接口的类必须提供接口中定义的方法
// 不能用接口创建对象,但是能够判断某个对象是否实现了某个接口
var_dump($coding instanceof Work); // 判断某个对象是否实现了某个接口

function checkWork($obj){
    if($obj instanceof Work){ //定义方法判断对象是否实现某个接口
        $obj->worker('coding');
  }else{
        echo "The programmer is playing basketball.";
  }
}
checkWork($coding);
checkWork($holiday);

接口的继承
interface Ainter
{
    public function func();
}

interface Binter extends Ainter
{
    public function test();
}

class MyClass implements Binter
{
    public function test(){
        
    }
}

一个类实现多个接口
interface Ainter
{
    public function func1();
}

interface Binter
{
    public function func2();
}

class MyClass implements Ainter,Binter
{
    public function func1(){

    }
    public function func2(){

    }
}

多态呢,到这里就自然明白了,只要对象实现了某个接口,就直接可以通过对象调用接口的所有方法,接口实现的类方法有很多,这种现象就称为多态,相同的代码传入的对象不一样,所以具体实现方式也不一样,这就是多态的真正含义。