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 相关文章推荐
解决phpmyadmin 乱码,支持gb2312和utf-8
Nov 20 PHP
PHP EOT定界符的使用详解
Sep 30 PHP
PHP 反射机制实现动态代理的代码
Oct 22 PHP
php中函数的形参与实参的问题说明
Sep 01 PHP
PHP生成RSS文件类实例
Dec 05 PHP
ThinkPHP通过AJAX返回JSON的两种实现方法
Dec 18 PHP
PHP开发注意事项总结
Feb 04 PHP
最准确的php截取字符串长度函数
Oct 29 PHP
WordPress用户登录框密码的隐藏与部分显示技巧
Dec 31 PHP
[原创]php简单防盗链验证实现方法
Jul 09 PHP
利用Homestead快速运行一个Laravel项目的方法详解
Nov 14 PHP
详解laravel安装使用Passport(Api认证)
Jul 27 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
火影忍者:这才是千手柱间和扉间的真正死因,角都就比较搞笑了!
2020/03/10 日漫
Yii框架中 find findAll 查找出制定的字段的方法对比
2014/09/10 PHP
php检查函数必传参数是否存在的实例详解
2017/08/28 PHP
[IE&amp;FireFox兼容]JS对select操作
2007/01/07 Javascript
JavaScript 异步调用框架 (Part 2 - 用例设计)
2009/08/03 Javascript
关于js类的定义
2011/06/28 Javascript
js实现运动logo图片效果及运动元素对象sportBox使用方法
2012/12/25 Javascript
JavaScript对象反射用法实例
2015/04/17 Javascript
JavaScript使用RegExp进行正则匹配的方法
2015/07/11 Javascript
常用原生JS兼容性写法汇总
2016/04/27 Javascript
微信小程序 switch组件详解及简单实例
2017/01/10 Javascript
将 vue 生成的 js 上传到七牛的实例
2017/07/28 Javascript
vue实现压缩图片预览并上传功能(promise封装)
2019/01/10 Javascript
泛谈JS逻辑判断选择器 || &amp;&amp;
2019/05/24 Javascript
使用vue中的混入mixin优化表单验证插件问题
2019/07/02 Javascript
antd Form组件方法getFieldsValue获取自定义组件的值操作
2020/10/29 Javascript
[05:00]第二届DOTA2亚洲邀请赛主赛事第三天比赛集锦.mp4
2017/04/04 DOTA
python局域网ip扫描示例分享
2014/04/03 Python
python模拟登陆阿里妈妈生成商品推广链接
2014/04/03 Python
python实现同时给多个变量赋值的方法
2015/04/30 Python
解析Mac OS下部署Pyhton的Django框架项目的过程
2016/05/03 Python
Python爬虫实现(伪)球迷速成
2018/06/10 Python
Python读取实时数据流示例
2019/12/02 Python
Python importlib模块重载使用方法详解
2020/10/13 Python
python打包生成so文件的实现
2020/10/30 Python
欧缇丽英国官方网站:Caudalie英国
2016/08/17 全球购物
局域网定义和特性
2016/01/23 面试题
自我评价格式
2014/01/06 职场文书
军训自我鉴定怎么写
2014/02/13 职场文书
党的群众路线教育实践活动整改落实情况报告
2014/10/28 职场文书
2014年餐厅服务员工作总结
2014/11/18 职场文书
治理商业贿赂工作总结
2015/08/10 职场文书
教师年度考核自我评鉴
2015/08/11 职场文书
javascript代码简写的几种常用方式汇总
2021/08/23 Javascript
使用redis生成唯一编号及原理示例详解
2021/09/15 Redis
【海涛解说】史上最给力比赛,挑战DOTA极限
2022/04/01 DOTA