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 相关文章推荐
在Windows版的PHP中使用ADO
Oct 09 PHP
杏林同学录(四)
Oct 09 PHP
同一空间绑定多个域名而实现访问不同页面的PHP代码
Dec 06 PHP
PHPMYADMIN 简明安装教程 推荐
Mar 07 PHP
php文件操作实例代码
May 10 PHP
关于ob_get_contents(),ob_end_clean(),ob_start(),的具体用法详解
Jun 24 PHP
PHP5.5和之前的版本empty函数的不同之处
Jun 13 PHP
PHP 数组基本操作小结(推荐)
Jun 13 PHP
通过chrome浏览器控制台(Console)进行PHP Debug的方法
Oct 19 PHP
PHP设计模式之模板方法模式定义与用法详解
Apr 02 PHP
windows 2008r2+php5.6.28环境搭建详细过程
Jun 18 PHP
PHP常用函数之格式化时间操作示例
Oct 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中一个完整表单处理实现代码
2011/11/10 PHP
thinkphp判断访客为手机端或PC端的方法
2014/11/24 PHP
PHP基于迭代实现文件夹复制、删除、查看大小等操作的方法
2017/08/11 PHP
Thinkphp自定义生成缩略图尺寸的方法
2019/08/05 PHP
Jqgrid表格随窗口大小改变而改变的简单实例
2013/12/28 Javascript
JavaScript实现鼠标滑过处生成气泡的方法
2015/05/16 Javascript
详解JavaScript基本类型和引用类型
2015/12/09 Javascript
干货分享:让你分分钟学会javascript闭包
2015/12/25 Javascript
jquery把int类型转换成字符串类型的方法
2016/10/07 Javascript
Angular 常用指令实例总结整理
2016/12/13 Javascript
Vue.js自定义指令的用法与实例解析
2017/01/18 Javascript
Javascript实现页面滚动时导航智能定位
2017/05/06 Javascript
利用yarn代替npm管理前端项目模块依赖的方法详解
2017/09/04 Javascript
微信小程序数字滚动插件使用详解
2018/02/02 Javascript
微信小程序使用wxParse解析html的实现示例
2018/08/30 Javascript
微信小程序第三方框架对比 之 wepy / mpvue / taro
2019/04/10 Javascript
[01:10]为家乡而战!完美世界城市挑战赛全国总决赛花絮
2019/07/25 DOTA
Django读取Mysql数据并显示在前端的实例
2018/05/27 Python
Python求解任意闭区间的所有素数
2018/06/10 Python
详解用python写网络爬虫-爬取新浪微博评论
2019/05/10 Python
python版DDOS攻击脚本
2019/06/12 Python
Python pip 安装与使用(安装、更新、删除)
2019/10/06 Python
win10系统下python3安装及pip换源和使用教程
2020/01/06 Python
html5/css3响应式页面开发总结
2018/10/16 HTML / CSS
法国珠宝店:CLEOR
2017/01/29 全球购物
美国台面电器和厨具品牌:KitchenAid
2019/04/12 全球购物
华为慧通面试题
2012/09/11 面试题
与C++相比,Java中的数组有什么不同
2014/03/25 面试题
药学专业大学生个人的自我评价
2013/11/04 职场文书
函授毕业自我鉴定
2014/02/04 职场文书
十八大标语口号
2014/10/09 职场文书
捐款感谢信
2015/01/20 职场文书
高中教师个人总结
2015/02/10 职场文书
Redis 配置文件重要属性的具体使用
2021/05/20 Redis
MySQL实战记录之如何快速定位慢SQL
2022/03/23 MySQL
Win10服务主机占用内存怎么办?Win10服务主机进程占用大量内存解决方法
2022/09/23 数码科技