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中动态显示签名和ip原理
Mar 28 PHP
php面向对象全攻略 (十六) 对象的串行化
Sep 30 PHP
php类中private属性继承问题分析
Nov 01 PHP
PHP中CURL方法curl_setopt()函数的参数分享
Jan 19 PHP
PHP中的事务使用实例
May 26 PHP
PHP实现清除wordpress里恶意代码
Oct 21 PHP
PHP数组实例详解
Jun 26 PHP
PHP实现二叉树深度优先遍历(前序、中序、后序)和广度优先遍历(层次)实例详解
Apr 20 PHP
基于Laravel(5.4版本)的基本增删改查操作方法
Oct 11 PHP
Laravel 微信小程序后端实现用户登录的示例代码
Nov 26 PHP
YII2框架中日志的配置与使用方法实例分析
Mar 18 PHP
is_file和file_exists效率比较
Mar 14 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
论坛头像随机变换代码
2006/10/09 PHP
15个小时----从修改程序到自己些程序
2006/10/09 PHP
深入理解php的MySQL连接类
2013/06/07 PHP
解javascript 混淆加密收藏
2009/01/16 Javascript
CSS+Table图文混排中实现文本自适应图片宽度(超简单+跨所有浏览器)
2009/02/14 Javascript
博客侧边栏模块跟随滚动条滑动固定效果的实现方法(js+jquery等)
2013/03/24 Javascript
页面定时刷新(1秒刷新一次)
2013/11/22 Javascript
通过pjax实现无刷新翻页(兼容新版jquery)
2014/01/31 Javascript
JavaScript格式化日期时间的方法和自定义格式化函数示例
2014/04/04 Javascript
实现网页页面跳转的几种方法(meta标签、js实现、php实现)
2014/05/20 Javascript
jquery中show()、hide()和toggle()用法实例
2015/01/15 Javascript
通过点击jqgrid表格弹出需要的表格数据
2015/12/02 Javascript
AngularJS表单和输入验证实例
2016/11/02 Javascript
ReactJs设置css样式的方法
2017/06/08 Javascript
axios+Vue实现上传文件显示进度功能
2019/04/14 Javascript
微信小程序官方动态自定义底部tabBar的例子
2019/09/04 Javascript
Python中下划线的使用方法
2015/03/27 Python
python登录豆瓣并发帖的方法
2015/07/08 Python
Python中运算符&quot;==&quot;和&quot;is&quot;的详解
2016/10/08 Python
Python+matplotlib实现华丽的文本框演示代码
2018/01/22 Python
pandas.loc 选取指定列进行操作的实例
2018/05/18 Python
python批量修改文件编码格式的方法
2018/05/31 Python
PyQt5创建一个新窗口的实例
2019/06/20 Python
python对绑定事件的鼠标、按键的判断实例
2019/07/17 Python
Python Django 封装分页成通用的模块详解
2019/08/21 Python
canvas实现按住鼠标移动绘制出轨迹的示例代码
2018/02/05 HTML / CSS
给定一个时间点,希望得到其他时间点
2013/11/07 面试题
门卫岗位职责
2013/11/15 职场文书
酒店销售主管岗位职责
2014/01/04 职场文书
数控机床专业自荐信
2014/05/19 职场文书
演讲比赛策划方案
2014/06/11 职场文书
学校会议通知范文
2015/04/15 职场文书
社区青年志愿者活动总结
2015/05/06 职场文书
2019年员工旷工保证书!
2019/06/28 职场文书
Windows10下安装MySQL8
2021/04/06 MySQL
MySQL添加索引特点及优化问题
2022/07/23 MySQL