抽象类,接口

Posted Just do it

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了抽象类,接口相关的知识,希望对你有一定的参考价值。

抽象类

  定义一个公共的基类(base class),而将特定的细节留给继承者来实现.

由于抽象类没有为它所声明的所有方法都定义实现,所以使用new操作符是不可以直接创建它的实例的.要创建实例,就必须创建另一个扩展抽象类的类,并重写所有之前声明的抽象方法原型.通过扩展类,我们就可以创建特殊的对象,而且它们同样能够保证提供一套公共的功能.

说明:方法的原型(prototype)是指方法的定义中剔除了方法体之后的签名.它包括存取级别,函数关键字,函数名和参数,它不包括({})或者括号内部的任何代码.例如 public function prototypeName($protoparam);就是一个i额方法的原型.

抽象类的特点:

  1.某个类只要包含至少一个抽象方法就必须声明为抽象类.

  2.声明为抽象的方法,在实现的时候必须包含相同的或者更低的访问级别.例如,如果某个方法在抽象类中的访问级别是受保护的,在继承类中就必须是受保护的或者公共的,而不能是私有的.

  3.不能使用new关键字创建抽象类的实例.

  4.被声明为抽象的方法不能包含函数体.

  5.如果将扩展的类也声明为抽象的,在扩展抽象类时,就可以不能实现所有的抽象方法.在创建具有层次结构的对象时,这种做法是很有用的.

在类的声明中使用abstract修饰符就可以将某个类声明为抽象的.

<?php

abstract class Car{
    //任何基类方法
    abstract function getMaximumSpeed();
}

class FastCar extends Car{
    function getMaximumSpeed(){
        return 150;
    }
}

class Street{
    protected $speedLimit;
    protected $cars;

    public function __construct($speedLimit = 200){
        $this->cars = array(); //对变量进行初始化
        $this->speedLimit = $speedLimit;
    }

    protected function isStreetLegal($car){
        if($car->getMaximumSpeed() < $this->speedLimit){
            return true;
        }else{
            return false;
        }
    }

    public function addCar($car){
        if($this->isStreetLegal($car)){
            echo \'The Car was allowed on the road.\';
            $this->car[] =$car;
        }else{
            echo \'The Car is too fast and was not allowed on the road.\';
        }
    }
}

$street = new Street();
$street->addCar(new FastCar());
    
    
View Code

  使用抽象类,我们就可以确定所有继承自Car的对象都会实现getMaximumSpeed()方法,从而

共享这个公共的功能.如果继承自Car的类没有定义这个方法,就会导致语法错误,程序也不会允许.

  然而,抽象类也有一些限制.php只支持从一个基类继承,而不支持从两个或者更多的抽象类继承.用接口可以达到相同的目的.

接口

  接口是一种类似于类的结构,可用于声明实现类所必须声明的方法.例如,接口通常用来声明API,而不用定义如何实现这个API.

  虽然接口与抽象类很相似,但是接口只能包含方法原型,而不能包含任何完整定义了的方法.这可以防止使用抽象类时可能出现的方法冲突,从而能在给定的实现类上使用多个接口.

  声明接口,需要使用关键字interface.

interface IExampleInterface{}

  和抽象类需要使用extends关键字不同的是,实现接口使用的是implements关键字.

Class ExampleClass implements IExampleInterface{}

  为了形成一个完整的类,我们必须实现接口中的所有方法,这样其他类才能依赖于接口中定义的所有方法.只要有一个接口方法没有实现,就会破坏定义公共接口的作用,因而这是不允许的.

//实现多接口
Class MyArrayLikeObject implements Iterator,Countable {}

抽象类和接口使用原则

  使用接口完全有可能实现与抽象类相同的操作.通常,在子类和父类之间存在有逻辑上的层次结构时,应该使用抽象类.而在希望支持差别较大的两个或者更多对象之间的特定交互行为时,使用抽象类就会显得不合理,此时应该使用接口.

instanceof 操作符

  instanceof操作符是PHP中的一个比较操作符.接受左右两边的参数,并返回Boolean类型的值.这个操作符是用来确定对象的某个实例是否为特定的类型,或者是否从某个类型继承,又或者是否实现了某个特定的接口.

上例代码用接口实现:

interface ISpeedInfo{
    function getMaximumSpeed();
}

class Car{
    //任何基类方法
}

class FastCar extends Car implements ISpeedInfo{
    function getMaximumSpeed(){
        return 150;
    }
}
    
class Street{
    protected $speedLimit;
    protected $cars;

    public function __construct($speedLimit = 200){
        $this->cars = array(); //对变量进行初始化
        $this->speedLimit = $speedLimit;
    }

    protected function isStreetLegal($car){
        if($car instanceof ISpeedInfo){
            if($car->getMaximumSpeed() < $this->speedLimit){
            return true;
        }else{
            return false;
        }
    }else{
        //扩展类必须实现ISpeedInfo才能使street合法
        return false;
    }
        
    }

    public function addCar($car){
        if($this->isStreetLegal($car)){
            echo \'The Car was allowed on the road.\';
            $this->cars[] =$car;
        }else{
            echo \'The Car is too fast and was not allowed on the road.\';
        }
    }
}

$street = new Street();
$street->addCar(new Street());
View Code

 

以上是关于抽象类,接口的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin接口和抽象类 ( 接口属性和方法定义 | 接口默认方法实现 | 抽象类 )

设计模式学习笔记 接口vs抽象类的区别?是否要为每个类定义接口?

接口和抽象类的相同与区别

接口和抽象类的相同与区别

抽象类和接口的异同

代码学习PHP面向对象之抽象类与接口