玩转PHP中的抽象类与接口

玩转PHP中的抽象类与接口

在面向对象开发中,特别是使用现代化框架的过程中,我们经常会和接口、抽象类打交道。特别是我们自己尝试去封装一些功能时,接口和抽象类往往会是我们开始的第一步,但你真的了解它们吗?

抽象类定义

抽象类的特点:

  • 顾名思义,它是抽象的,当然也就是不能被实例化的。所以,抽象类一般是作为我们的基类来进行定义的。
  • 在一个类中,只要有一个方法被定义为抽象的,那么这个类就必须加上abstract关键字成为抽象类。
  • 被定义为抽象的方法只声明其调用方式,不能定义其具体的功能实现。
  • 子类必须定义父类中的所有抽象方法,这些方法的访问控制必须和父类一致或者更为宽松。
  • 方法的调用方式必须匹配,即类型和所需参数数量必须一致。子类实现的抽象方法可以增加参数但必须有默认值。

abstract class A {
public function show(){
$this->getName();
echo PHP_EOL;
}

protected abstract function getName();
public abstract function getAge($age);
}

class ChildA1 extends A {
public function getName(){
echo "I'm ChildA1";
}
public function getAge($age){
echo "Age is " . $age;
}
}

class ChildA2 extends A {
protected function getName(){
echo "I'm ChildA2";
}
public function getAge($age, $year = ''){
echo "Age is ". $age . ', bron ' . $year;
}
}

$ca1 = new ChildA1();
$ca1->show();
$ca1->getAge(18);

$ca2 = new ChildA2();
$ca2->show();
$ca2->getAge(20, 2000);

接口定义

接口的特点:

  • 可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。
  • 就像定义一个标准的类一样,但其中定义所有的方法都是空的。
  • 接口中定义的所有方法都必须是公有,这是接口的特性。
  • 类中必须实现接口中定义的所有方法,否则会报一个致命错误。类可以实现多个接口,用逗号来分隔多个接口的名称。
  • 类要实现接口,必须使用和接口中所定义的方法完全一致的方式。否则会导致致命错误
  • 接口也可以继承,通过使用 extends 操作符
  • 接口中也可以定义常量。接口常量和类常量的使用完全相同,但是不能被子类或子接口所覆盖

interface B1 {
const B1_NAME = 'Interface B1';
function getName();
function getAge($age);
}

interface B2 extends B1 {
function show();
}

interface B3 {
function getSchool();
}

class ChildB implements B2, B3{
function getName(){
echo "I'm ChildB";
}
function getAge($age, $year = ''){
echo "Age is " . $age;
}
function show(){
$this->getName();
echo PHP_EOL;

$this->getAge(23, 1997);
echo PHP_EOL;

echo self::B1_NAME;
echo PHP_EOL;
}

function getSchool(){
echo "study in Peking University";
echo PHP_EOL;
}
}

$b = new ChildB();
$b->show();
$b->getSchool();

抽象类和接口的区别

从上面我们可以总结出一些抽象类和接口的区别:

  • 抽象类的子类遵循继承原则,只能有一个父类;但一个类可以实现多个接口
  • 抽象类中可以有非抽象的已经实现的方法;接口中全是抽象的方法,都是方法定义
  • 抽象类中方法和变量的访问控制自己定义;接口中只能是公共的

那么问题来了,这两货哪个好?抱歉,这个问题可没有答案,它们的作用不同。抽象类可以作为基类,为子类提供公共方法,并定制公共的抽象让子类来实现。而接口则是更高层次的抽象,它可以让我们依赖于抽象而不是具体的实现,为软件开发带来更多的扩展性。

面向接口开发

接口,实际上也可以看做是一种契约。我们经常会拿电脑主机箱后面的插口来说明。比如USB接口,我们定义了它的大小,里面的线路格式,不管你插进来的是什么,我们都可以连通。而具体的实现则是取决于电脑软件对插入的硬件的解释,比如U盘就会去读取它里面的内容,而键盘则会识别为一个外设。

从这里可以看出,接口能够为我们程序的扩展提供非常强大的支撑。任何面向对象语言中接口都是非常重要的特性。下面我们来用接口模拟刚刚说的USB插口。

interface USB{
function run();
}

class Keyboard implements USB{
function run(){
echo "这是键盘";
}
}

class UDisk implements USB{
function run(){
echo "这是U盘";
}
}

这么写有什么好处呢?我们再深入一个概念:依赖注入。如果使用面向接口开发的话:

function testUSB (USB $u){
$u->run();
}

// 插入U盘
testUSB(new UDisk);

// 插入键盘
testUSB(new Keyboard);

testUSB方法中的$u并不是某个具体实例,只是USB接口的抽象,在不知道它是什么实例的情况下我们通过接口契约,保证它一定会有一个run()方法。而具体的实现,则是在外部我们调用方法的时候注入进来的。

总结

掌握好接口的设计原则,往往就能看懂一大半的框架的设计思想。这也是我们面向对象中最最基础的特性。抽象类作为公共基类来说可以为多态提供比较好的范本,它能够让你的子类有自己的个性又能使用父类的能力。总之,深入场景业务,选择合适的方式实现代码,靠的是能力、经验与智慧的综合,决不是一句谁好谁不好所能定性的。

测试代码:https://github.com/zhangyue0503/dev-blog/blob/master/php/201912/source/%E7%8E%A9%E8%BD%ACPHP%E4%B8%AD%E7%9A%84%E6%8A%BD%E8%B1%A1%E7%B1%BB%E4%B8%8E%E6%8E%A5%E5%8F%A3.php

参考文档:https://www.php.net/manual/zh/language.oop5.abstract.phphttps://www.php.net/manual/zh/language.oop5.interfaces.phphttps://www.php.net/manual/zh/language.oop5.interfaces.php#79110

(0)

相关推荐

  • PHP中命名空间是怎样的存在(一)?

    命名空间其实早在PHP5.3就已经出现了.不过大部分同学可能在各种框架的使用中才会接触到命名空间的内容,当然,现代化的开发也都离不开这些能够快速产出的框架.这次我们不从框架的角度,仅从简单的代码角度来 ...

  • final关键字在PHP中的使用

    final关键字的使用非常简单,在PHP中的最主要作用是定义不可重写的方法.什么叫不可重写的方法呢?就是子类继承后也不能重新再定义这个同名的方法. class A { final function t ...

  • [PHP小课堂]玩转PHP中的抽象类与接口

    [PHP小课堂]玩转PHP中的抽象类与接口 关注公众号:[硬核项目经理]获取最新文章 添加微信/QQ好友:[DarkMatterZyCoder/149844827]免费得PHP.项目管理学习资料 B站 ...

  • 玩转空间中的神圣光影

    Hello 小伙伴们,新年伊始,又到了每周一的制图教室时间啦~ "光",似乎是建筑设计永远绕不开的话题,精心设计的光影往往成为一幢建筑给人最深刻的体验,当我们的方案对光影变幻进行了 ...

  • 玩转犀牛中的BIM第三期: VisualARQ2.8&Rhino6全模出图工作流

    「 前 言 」 随着异形建筑和参数化设计在大陆的不断普及,越来越多的建筑学小伙伴开始选择采用Rhino&Grasshopper作为主要的建模软件,网络上也应运而生了大量关于Rhino建模的案例 ...

  • 玩基过程中的“小舍”与“大得”玩基金很多...

    玩基过程中的"小舍"与"大得" 玩基金很多时候都是在玩风口,再好的板块.在低的估值.在没有风口到来之前,他可以让你感受到绝望,甚至可以跌到地下室! 相反,在风口 ...

  • 《早安京剧》续语(89)玩中学 学中乐 乐中进

    <早安续语>(八十九)玩中学 学中乐  乐中进 票友对待业余京剧活动,是图娱乐呢?还是图学呢?大部分是图娱乐,那就开心玩儿吧,一段"自那日"能唱二十年不变样儿,也无所谓.但如果是 ...

  • 靳东玩无辜,采访中语出惊人,说自己和娱乐圈没一毛钱关系

    靳东因为在微博上引用梵高一句话"在这薄情的世界里深情的活着"从而引发争议,因为这句话并不是梵高说的,而是后人对梵高一生的经历的总结.具体这句话的原作者是谁,说法不一,有人说是出自佚 ...

  • 惹“火”上身!大佬基金爆仓,高杠杆“玩法”引发中概股“多米诺骨牌式”暴跌

    近期,中概股发生诡异大跌! 一个大佬的基金爆仓,引起了一场席卷中概股市场的蝴蝶效应. 多米诺骨牌式暴跌 3月29日美股开盘,中概股出现分化.截至发稿,跟谁学大跌14.71%,腾讯音乐跌2.44%,百度 ...

  • 电路中7个常用接口类型之要点说明

    我们知道,在电路系统的各个子模块进行数据交换时可能会存在一些问题导致信号无法正常.高质量地"流通",例如有时电路子模块各自的工作时序有偏差(如CPU与外设)或者各自的信号类型不一致 ...

  • 游戏中的传统文化|在“玩”和“食”中感知端午 亲近传统

    端 午 DRAGON BOAT FESTIVAL 端午节是我国四大传统节日之一. 当传统节日与游戏节相遇, 石榴幼大家族开展传统游戏日活动, 把传统节日习俗 化为可操作可感知的学习, 让孩子们在玩.食 ...