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写的serv-u的web申请账号的程序
Oct 09 PHP
php 3行代码的分页算法(求起始页和结束页)
Oct 21 PHP
PHP读取ACCESS数据到MYSQL的代码
May 11 PHP
php中的三元运算符使用说明
Jul 03 PHP
安装apache2.2.22配置php5.4(具体操作步骤)
Jun 26 PHP
解析PHP中VC6 X86和VC9 X86的区别及 Non Thread Safe的意思
Jun 28 PHP
Codeigniter实现多文件上传并创建多个缩略图
Jun 12 PHP
destoon出现验证码不显示时的紧急处理方法
Aug 22 PHP
浅析php原型模式
Nov 25 PHP
PHP滚动日志的代码实现
Jun 10 PHP
PHP6连接SQLServer2005的三部曲
Apr 15 PHP
php 从一个数组中随机的取出若干个不同的数实例
Dec 31 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开启gzip页面压缩实例代码
2010/03/11 PHP
thinkPHP中create方法与令牌验证实例浅析
2015/12/08 PHP
window.onbeforeunload方法在IE下无法正常工作的解决办法
2010/01/23 Javascript
window.open不被拦截的实现代码
2012/08/22 Javascript
jqGrid随窗口大小变化自适应大小的示例代码
2013/12/28 Javascript
JavaScript实现更改网页背景与字体颜色的方法
2015/02/02 Javascript
基于JavaScript实现手机短信按钮倒计时(超简单)
2015/12/30 Javascript
BootStrap下jQuery自动完成的样式调整
2016/05/30 Javascript
JS控制文本域只读或可写属性的方法
2016/06/24 Javascript
JS实现快速的导航下拉菜单动画效果附源码下载
2016/11/01 Javascript
jQuery中的deferred使用方法
2017/03/27 jQuery
深入理解ES7的async/await的用法
2017/09/09 Javascript
Vue调试神器vue-devtools安装方法
2017/12/12 Javascript
vue-devtools的安装步骤
2018/04/23 Javascript
关于vue-router的那些事儿
2018/05/23 Javascript
Node.js命令行/批处理中如何更改Linux用户密码浅析
2018/07/22 Javascript
vue如何限制只能输入正负数及小数
2019/07/04 Javascript
vue实现修改图片后实时更新
2019/11/14 Javascript
vue中axios防止多次触发终止多次请求的示例代码(防抖)
2020/02/16 Javascript
[02:59]DOTA2完美大师赛主赛事第三日精彩集锦
2017/11/25 DOTA
[01:06:25]Secret vs Liquid 2018国际邀请赛淘汰赛BO3 第一场 8.25
2018/08/29 DOTA
使用python搭建Django应用程序步骤及版本冲突问题解决
2013/11/19 Python
Python OpenCV处理图像之图像直方图和反向投影
2018/07/10 Python
Python tkinter和exe打包的方法
2020/02/05 Python
使用Python 自动生成 Word 文档的教程
2020/02/13 Python
python实现网页录音效果
2020/10/26 Python
CSS3 伪类选择器 nth-child()说明
2010/07/10 HTML / CSS
租车协议书范本2014
2014/11/17 职场文书
2015年公务员转正工作总结
2015/04/24 职场文书
少先队入队仪式主持词
2015/07/04 职场文书
先进工作者主要事迹材料
2015/11/03 职场文书
2019朋友新婚祝福语精选
2019/10/10 职场文书
Pygame Draw绘图函数的具体使用
2021/11/17 Python
全面盘点MySQL中的那些重要日志文件
2021/11/27 MySQL
Nginx反向代理、重定向
2022/04/13 Servers
Redis主从复制操作和配置详情
2022/09/23 Redis