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 相关文章推荐
用PHP+MySql编写聊天室
Oct 09 PHP
FCKeditor添加自定义按钮
Mar 27 PHP
PHP 存储文本换行实现方法
Jan 05 PHP
php的POSIX 函数以及进程测试的深入分析
Jun 03 PHP
php strrpos()与strripos()函数
Aug 31 PHP
PHP获取浏览器信息类和客户端地理位置的2个方法
Apr 24 PHP
ThinkPHP中公共函数路径和配置项路径的映射分析
Nov 22 PHP
PHP扩展开发入门教程
Feb 26 PHP
详解PHP+AJAX无刷新分页实现方法
Nov 03 PHP
PHP实现QQ登录实例代码
Jan 14 PHP
PHP实现的DES加密解密封装类完整实例
Apr 29 PHP
php单元测试phpunit入门实例教程
Nov 17 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
使用zend studio for eclipse不能激活代码提示功能的解决办法
2009/10/11 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(一)
2014/06/23 PHP
php开发时容易忘记的一些技术细节
2016/02/03 PHP
在Yii2中使用Pjax导致Yii2内联脚本载入失败的原因分析
2016/03/06 PHP
php出租房数据管理及搜索页面
2017/05/23 PHP
javascript基础第一章 JavaScript与用户端
2010/07/22 Javascript
javascript不同类型数据之间的运算的转换方法
2014/02/13 Javascript
简单实现JavaScript图片切换效果
2016/11/28 Javascript
详谈jQuery中的一些正则匹配表达式
2017/03/08 Javascript
JavaScript函数绑定用法实例分析
2017/11/14 Javascript
解决Vue.js 2.0 有时双向绑定img src属性失败的问题
2018/03/14 Javascript
vue.js input框之间赋值方法
2018/08/24 Javascript
Vue axios设置访问基础路径方法
2018/09/19 Javascript
基于Vue 服务端Cookies删除的问题
2018/09/21 Javascript
Vue中Table组件Select的勾选和取消勾选事件详解
2019/03/19 Javascript
微信小程序可滑动月日历组件使用详解
2019/10/21 Javascript
vue实现在线预览pdf文件和下载(pdf.js)
2019/11/26 Javascript
python+matplotlib演示电偶极子实例代码
2018/01/12 Python
使用django-guardian实现django-admin的行级权限控制的方法
2018/10/30 Python
Python设计模式之简单工厂模式实例详解
2019/01/22 Python
总结python中pass的作用
2019/02/27 Python
计算机二级python学习教程(1) 教大家如何学习python
2019/05/16 Python
python pytest进阶之conftest.py详解
2019/06/27 Python
tensorflow 分类损失函数使用小记
2020/02/18 Python
python实现ssh及sftp功能(实例代码)
2020/03/16 Python
美国名牌香水折扣网站:Hottperfume
2021/02/10 全球购物
什么是类的返射机制
2016/02/06 面试题
高中历史教学反思
2014/02/08 职场文书
规划编制实施方案
2014/03/15 职场文书
保护环境倡议书500字
2014/05/19 职场文书
争先创优心得体会
2014/09/12 职场文书
个人查摆剖析材料
2014/10/16 职场文书
感恩母亲节活动总结
2015/02/10 职场文书
《当代神农氏》教学反思
2016/02/23 职场文书
2019年XX公司的晨会制度及流程!
2019/07/23 职场文书
python将图片转为矢量图的方法步骤
2021/03/30 Python