PHP抽象类与接口的区别实例详解


Posted in PHP onMay 09, 2019

本文实例讲述了PHP抽象类与接口的区别。分享给大家供大家参考,具体如下:

抽象类abstract

概念

定义为抽象的类不能被实例化。任何一个类,如果有一个方法是被声明为抽象的,那么这个类就必须被声明为抽象的类。

继承一个抽象类的时候,子类必须定义父类中的所有抽象方法,这些方法的访问控制必须喝父类中一样或者更为宽松。

例如,某个抽象方法被声明为proteced,那么子类中的实现,就应该声明为protected或者public,而不能定义为private。

方法的调用方式必须匹配,即类型和所需参数数量必须一致,例如,子类定义了一个可选参数,而父类抽象方法中没有声明,则两者的声明并没有冲突。

特点

  • 抽象类继承,使用关键字extends。
  • 抽象类可以声明各种变量、常量、方法。
  • 抽象类可以有构造函数。
  • 抽象类中的方法可以是公开的public、保护的protected、私有的private。
  • 一个类只能继承一个抽象类。

示例

示例一

<?php
// 抽象类
abstract class AbstractClasss
{
  // 强制要求子类定义这些方法
  abstract protected function getValue();
  abstract protected function prefixValue();
  // 普通方法(非抽象方法)
  public function printOut() 
  {
    print $this->getValue() . "\n";
  }
}
// 子类
class ConcreteClassOne extends AbstractClass
{
  protected function getValue()
  {
    return "ConcreteClassOne";
  }
  public function prefixValues($prefix)
  {
    return "{$prefix}ConcreteClassOne";
  }
}
// 子类
class ConcreteClassTwo extends AbstractClass
{
  protected function getValue()
  {
    return "ConcreteClassTwo";
  }
  public function prefixValue($prefix)
  {
    return "{$prefix}ConcreteClassTwo";
  }
}
// 实例化第一个子类
$classOne = new ConcreteClassOne;
$classOne->printOut();
echo $classOne->prefixValue('FOO_') . "\n";
// 实例化第二个子类
$classTwo = new ConcreteClassTwo;
$classTwo->printOut();
echo $classTwo->prefixValue('FOO_') . "\n";

结果输出

ConcreteClassOne
FOO_ConcreteClassOne

ConcreteClassTwo
FOO_ConcreteClassTwo

示例二

<?php
// 抽象类
abstract class AbstractClass
{
  // 我们的抽象方法仅需要定义需要的参数
  abstract protected function prefixName($name);
}
// 子类
class ConcreteClass extends AbstractClass
{
  // 我们的子类可以定义父类签名中不存在的可选参数
  public function prefixName($name, $separator = ".")
  {
    if ($name == "Pacman") {
      $prefix = "Mr";
    } elseif ($name == "Pacwoman") {
      $prefix = "Mrs";
    } else {
      $prefix = "";
    }
    return "{$prefix}{$separator} {$name}";
  }
}
// 实例化子类
$class = new ConcreteClass;
echo $class->prefixName("Pacman") . "\n";
echo $class->prefixName("Pacwoman") . "\n";

结果输出

Mr. Pacman
Mrs, Pacwoman

接口interface

概念

使用接口interface,可以指定某个类必须实现那些方法,但是不需要定义这些方法的具体内容。

要实现一个接口,使用implements操作符,类中必须实现接口中定义的所有方法。

特点

  • 接口的实现,使用关键字implements。
  • 接口中不能声明变量,但是可以声明常量。
  • 接口中没有构造函数。
  • 接口中的方法默认都是公开的public。
  • 一个类可以实现多个接口。

示例

示例一 、 实现接口

<?php
// 声明一个iTemplate接口
interface iTemplate
{
  public function setVariable($name, $var);
  public function getHtml($template);
}
// 实现接口
// 下面的写法是正确的
class Template implements iTemplate
{
  private $vars = array();
  public function setVariable($name, $var)
  {
    $this->vars[$name] = $var;
  }
  public function getHtml($template)
  {
    foreach($this->vars as $name => $value) {
      $template = str_replace('{' . $name . '}', $value, $template);
    }
    return $template;
  }
}
// 下面的写法是错误的,会报错,因为没有实现 getHtml()
// Fatal error: Class BadTemplate contains 1 abstract methonds
// and must therefore be declared abstaract (iTemplate::getHtml)
class BadTemplate implements iTemplate
{
  private $vars = array();
  public function setVariable($name, $var)
  {
    $this->vars[$name] = $var;
  }
}

示例二 、 可扩充接口

<?php
interface a
{
  public function foo();
}
interface b extends a
{
  public function baz(Baz $baz);
}
// 正确的写法
class c implements b
{
  public function foo()
  {
  }
  public function baz(Baz $baz)
  {
  }
}
// 错误的写法会导致一个致命的错误
class d implements b
{
  public function foo()
  {
  }
  public function baz(Foo $foo)
  {
  }
}

示例三 、 继承多个接口

<?php
interface a
{
  pubLic function foo();
}
interface b
{
  public function bar();
}
interface c extends a, b
{
  public function baz();
}
class d implements c
{
  public function foo()
  {
  }
  public function bar()
  {
  }
  public function baz()
  {
  }
}

示例四 、使用接口常量

<?php
interface a
{
  const b = 'Interface constant';
}
// 输出接口变量
echo a:b;
// 错误的写法,因为常量不能被覆盖。
// 接口常量的概念和类常量的是一样的。
class b implements a
{
  const b = 'Class constant'
}

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
shopex中集成的站长统计功能的代码简单分析
Aug 11 PHP
sql注入与转义的php函数代码
Jun 17 PHP
PHP 面向对象程序设计(oop)学习笔记(三) - 单例模式和工厂模式
Jun 12 PHP
ThinkPHP中Session用法详解
Nov 29 PHP
简单谈谈PHP vs Node.js
Jul 17 PHP
以实例全面讲解PHP中多进程编程的相关函数的使用
Aug 18 PHP
php自定义扩展名获取函数示例
Dec 12 PHP
PHP观察者模式原理与简单实现方法示例
Aug 25 PHP
PHP基于mcript扩展实现对称加密功能示例
Feb 21 PHP
yii框架使用分页的方法分析
Jul 25 PHP
laravel-admin 在列表页添加自定义按钮的例子
Sep 30 PHP
PHP pthreads v3下同步处理synchronized用法示例
Feb 21 PHP
php和vue配合使用技巧和方法
May 09 #PHP
php查询内存信息操作示例
May 09 #PHP
PHP利用百度ai实现文本和图片审核
May 08 #PHP
PHP回调函数简单用法示例
May 08 #PHP
Thinkphp5+plupload实现的图片上传功能示例【支持实时预览】
May 08 #PHP
PHP封装类似thinkphp连贯操作数据库Db类与简单应用示例
May 08 #PHP
php封装的pdo数据库操作工具类与用法示例
May 08 #PHP
You might like
php获取mysql数据库中的所有表名的代码
2011/04/23 PHP
一些需要禁用的PHP危险函数(disable_functions)
2012/02/23 PHP
PHP中怎样防止SQL注入分析
2014/10/23 PHP
PHP5.4起内置web服务器使用方法
2016/08/09 PHP
利用Homestead快速运行一个Laravel项目的方法详解
2017/11/14 PHP
jQuery实现动画效果circle实例
2015/08/06 Javascript
JavaScript+CSS无限极分类效果完整实现方法
2015/12/22 Javascript
JavaScript中的this机制
2016/01/30 Javascript
多种JQuery循环滚动文字图片效果代码
2020/06/23 Javascript
微信小程序 rich-text的使用方法
2017/08/04 Javascript
解决在vue+webpack开发中出现两个或多个菜单公用一个组件问题
2017/11/28 Javascript
vue中使用iview自定义验证关键词输入框问题及解决方法
2018/03/26 Javascript
动态加载JavaScript文件的3种方式
2018/05/05 Javascript
在Vue中使用axios请求拦截的实现方法
2018/10/25 Javascript
Angular6 发送手机验证码按钮倒计时效果实现方法
2019/01/08 Javascript
微信小程序手动添加收货地址省市区联动
2020/05/18 Javascript
解决vue scoped html样式无效的问题
2020/10/24 Javascript
Fiddler如何抓取手机APP数据包
2016/01/22 Python
python+Django+apache的配置方法详解
2016/06/01 Python
Python自动化测试笔试面试题精选
2020/03/12 Python
Python的PIL库中getpixel方法的使用
2020/04/09 Python
python实现坦克大战
2020/04/24 Python
Python基于pip实现离线打包过程详解
2020/05/15 Python
基于SQLAlchemy实现操作MySQL并执行原生sql语句
2020/06/10 Python
Python xpath表达式如何实现数据处理
2020/06/13 Python
html5使用canvas绘制太阳系效果
2014/12/15 HTML / CSS
美国当红的名品折扣网:Gilt Groupe
2016/08/15 全球购物
儿科护士实习自我鉴定
2013/10/17 职场文书
销售副总经理岗位职责
2013/12/11 职场文书
全民健身日活动方案
2014/01/29 职场文书
建设投标担保书
2014/05/13 职场文书
争当四好少年演讲稿
2014/09/13 职场文书
公司费用报销管理制度
2015/08/04 职场文书
Golang中异常处理机制详解
2021/06/08 Golang
Spring Cloud Netflix 套件中的负载均衡组件 Ribbon
2022/04/13 Java/Android
Java版 简易五子棋小游戏
2022/05/04 Java/Android