php抽象类abstract与接口理解与示…

2023-05-16

PHP抽象类abstract的理解对于初学者来说不是非常熟悉,我们还需要在不断的代码积累中来积累这方面的知识。其实抽象类和接口类有一部分很像。

 

记得在哪里看见这样一句话,抽象类就把类像的部分抽出来,这句看上去很搞笑,其实它说出了抽象类的真理,抽象类的作用是,当你发现你的很多类里面用很多方法你不断的在重复写,那你就可以考虑使用抽象类了,你可能会说“我不是可以重写一个类每个公共类我个实例化一个这个公共类,调用相同的方法就可以了”,这里是可以,实际上抽象类做的工作也就是这个,不过他省去了你实例化的这个步骤,让你就像直接调用PHP抽象类abstract方法一样方便,而且你还可以重载这个方法。如:


  
  1. abstract class BaseShop  
  2. {  
  3. public function buy($gid)  
  4. {  
  5. echo('你购买了ID为 :'.$gid.'的商品');  
  6. }  
  7. public function sell($gid)  
  8. {  
  9. echo('你卖了ID为 :'.$gid.'的商品');  
  10. }  
  11. public function view($gid)  
  12. {  
  13. echo('你查看了ID为 :'.$gid.'的商品');  
  14. }  
  15. }  
  16. class BallShop extends BaseShop  
  17. {  
  18. var $itme_id null;  
  19. public function __construct()  
  20. {  
  21. $this->itme_id 2314;  
  22. }  
  23. public function open()  
  24. {  
  25. $this->sell($this->itme_id);  
  26. }  

这里是一个例子,想上面一样我定义了一个商店类,抽出了它所有像的部分,买(buy),卖(sell),看(view),并且抽象类里都实现了这些方法,那么继承它的子类就自动获得了这些方法,子类就做它自己独特的东西,介绍代码的重复,提高复用性。

结论: PHP抽象类abstract就是一个类的服务提供商,拥有众多服务,你不用必须用,当需要的时候你来用就可以,如果你觉得不提供服务不满意,你还可以自己来做。

 

加深理解与运用

一、 抽象类abstract class

1 .抽象类是指在 class 前加了 abstract 关键字且存在抽象方法(在类方法 function 关键字前加了 abstract 关键字)的类。

2 .抽象类不能被直接实例化。抽象类中只定义(或部分实现)子类需要的方法。子类可以通过继承抽象类并通过实现抽象类中的所有抽象方法,使抽象类具体化。

3 .如果子类需要实例化,前提是它实现了抽象类中的所有抽象方法。如果子类没有全部实现抽象类中的所有抽象方法,那么该子类也是一个抽象类,必须在 class 前面加上 abstract 关键字,并且不能被实例化。

    代码如下:

abstract class A 

         
        protected $value1 = 0; 
        private $value2 = 1; 
        public $value3 = 2; 
         
        public function my_print() 
       
                echo "hello,world/n"; 
       
         
        abstract protected function abstract_func1(); 
        abstract protected function abstract_func2(); 

abstract class B extends A 

        public function abstract_func1() 
       
              echo "implement the abstract_func1 in class A/n"; 
       
         
        //abstract protected function abstract_func2(); 

class C extends B 

        public function abstract_func2() 
       
              echo "implement the abstract_func2 in class A/n"; 
       

4 .如果像下面这样创建了一个继承自 A 的子类 B ,但是不实现抽象方法 abstract_func() :

    代码如下:

Class B extends A{};

 那么程序将出现以下错误:

 

  代码如下:

  Fatal error: Class B contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (A::abstract_func)
 

 5 .如果 B 实现了抽象方法 abstract_func() ,那么 B 中 abstract_func() 方法的访问控制不能比 A 中 abstract_func() 的访问控制更严格,也就是说:

(1)      如果 A 中 abstract_func() 声明为 public ,那么 B 中 abstract_func() 的声明只能是 public ,不能是 protected 或 private

(2)      如果 A 中 abstract_func() 声明为 protected ,那么 B 中 abstract_func() 的声明可以是 public 或 protected ,但不能是 private

(3)      如果 A 中 abstract_func() 声明为 private ,嘿嘿,不能定义为 private 哦!( Fatal error : Abstract function A::abstract_func() cannot be declared private )

二、 接口interface

1 .抽象类提供了具体实现的标准,而接口则是纯粹的模版。接口只定义功能,而不包含实现的内容。接口用关键字 interface 来声明。

2 . interface 是完全抽象的,只能声明方法,而且只能声明 public 的方法,不能声明 private 及 protected 的方法,不能定义方法体,也不能声明实例变量 。然而, interface 却可以声明常量变量 。但将常量变量放在 interface 中违背了其作为接口的作用而存在的宗旨,也混淆了 interface 与类的不同价值。如果的确需要,可以将其放在相应的 abstract class 或 Class 中。

    代码如下:

interface iA 

        const AVAR=3; 
        public function iAfunc1(); 
        public function iAfunc2(); 

echo iA:: AVAR;

3 .任何实现接口的类都要实现接口中所定义的所有方法

    代码如下:

class E implements iA 

        public function iAfunc1(){echo "in iAfunc1";} 
        public function iAfunc2(){echo "in iAfunc2";} 

否则该类必须声明为 abstract 。

    代码如下:

abstract class E implements iA{} 

4 .一个类可以在声明中使用 implements 关键字来实现某个接口。这么做之后,实现接口的具体过程和继承一个仅包含抽象方法的抽象类是一样的。一个类可以同时继承一个父类和实现任意多个接口。 extends 子句应该在 implements 子句之前。 PHP 只支持继承自一个父类,因此 extends 关键字后只能跟一个类名。

  代码如下:

interface iB 

        public function iBfunc1(); 
        public function iBfunc2(); 

class D extends A implements iA,iB 

        public function abstract_func1() 
       
              echo "implement the abstract_func1 in class A/n"; 
       
        public function abstract_func2() 
       
              echo "implement the abstract_func2 in class A/n"; 
       
        public function iAfunc1(){echo "in iAfunc1";} 
        public function iAfunc2(){echo "in iAfunc2";} 
        public function iBfunc1(){echo "in iBfunc1";} 
        public function iBfunc2(){echo "in iBfunc2";} 


class D extends B implements iA,iB 

        public function abstract_func1() 
       
              parent::abstract_func1(); 
              echo "override the abstract_func1 in class A/n"; 
       
        public function abstract_func2() 
       
              echo "implement the abstract_func2 in class A/n"; 
       
        public function iAfunc1(){echo "in iAfunc1";} 
        public function iAfunc2(){echo "in iAfunc2";} 
        public function iBfunc1(){echo "in iBfunc1";} 
        public function iBfunc2(){echo "in iBfunc2";} 

5 .接口不可以实现另一个接口,但可以继承多个

  代码如下:

interface iC extends iA,iB{} 
class F implements iC 

        public function iAfunc1(){echo "in iAfunc1";} 
        public function iAfunc2(){echo "in iAfunc2";} 
        public function iBfunc1(){echo "in iBfunc1";} 
        public function iBfunc2(){echo "in iBfunc2";} 

三、 抽象类和接口的异同

1. 相同点:

(1)      两者都是抽象类,都不能实例化。

(2)      interface 实现类及 abstract class 的子类都必须要实现已经声明的抽象方法。

2. 不同点:

(1)      interface 需要实现,要用 implements ,而 abstract class 需要继承,要用 extends 。

(2)      一个类可以实现多个 interface ,但一个类只能继承一个 abstract class 。

(3)      interface 强调特定功能的实现,而 abstract class 强调所属关系。

(4)      尽管 interface 实现类及 abstract class 的子类都必须要实现相应的抽象方法,但实现的形式不同。 interface 中的每一个方法都是抽象方法,都只是声明的 (declaration, 没有方法体 ) ,实现类必须要实现。而 abstract class 的子类可以有选择地实现。这个选择有两点含义: a) abstract class 中并非所有的方法都是抽象的,只有那些冠有 abstract 的方法才是抽象的,子类必须实现。那些没有 abstract 的方法,在 abstract class 中必须定义方法体; b) abstract class 的子类在继承它时,对非抽象方法既可以直接继承,也可以覆盖;而对抽象方法,可以选择实现,也可以留给其子类来实现,但此类必须也声明为抽象类。既是抽象类,当然也不能实例化。

(5)      abstract class 是 interface 与 class 的中介。 abstract class 在 interface 及 class 中起到了承上启下的作用。一方面, abstract class 是抽象的,可以声明抽象方法,以规范子类必须实现的功能;另一方面,它又可以定义缺省的方法体,供子类直接使用或覆盖。另外,它还可以定义自己的实例变量,以供子类通过继承来使用。

(6)      接口中的抽象方法前不用也不能加 abstract 关键字,默认隐式就是抽象方法,也不能加 final 关键字来防止抽象方法的继承。而抽象类中抽象方法前则必须加上 abstract 表示显示声明为抽象方法。

(7)      接口中的抽象方法默认是 public 的,也只能是 public 的,不能用 private , protected 修饰符修饰。而抽象类中的抽象方法则可以用 public , protected 来修饰,但不能用 private 。

3. interface 的应用场合

(1)      类与类之间需要特定的接口进行协调,而不在乎其如何实现。

(2)      作为能够实现特定功能的标识存在,也可以是什么接口方法都没有的纯粹标识。

(3)      需要将一组类视为单一的类,而调用者只通过接口来与这组类发生联系。

(4)      需要实现特定的多项功能,而这些功能之间可能完全没有任何联系。

4. abstract class 的应用场合

一句话,在既需要统一的接口,又需要实例变量或缺省的方法的情况下,就可以使用它。最常见的有:

(1)      定义了一组接口,但又不想强迫每个实现类都必须实现所有的接口。可以用 abstract class 定义一组方法体,甚至可以是空方法体,然后由子类选择自己所感兴趣的方法来覆盖。

(2)      某些场合下,只靠纯粹的接口不能满足类与类之间的协调,还必需类中表示状态的变量来区别不同的关系。 abstract 的中介作用可以很好地满足这一点。

(3)      规范了一组相互协调的方法,其中一些方法是共同的,与状态无关的,可以共享的,无需子类分别实现;而另一些方法却需要各个子类根据自己特定的状态来实现特 定的功能 。

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

php抽象类abstract与接口理解与示… 的相关文章

  • 纠正装饰器模式的一个大缺点

    不久前 我在重构一些游戏战斗代码时决定尝试装饰器模式 战斗者可以拥有各种被动能力 也可能是不同类型的生物 我认为装饰器可以让我在运行时以各种组合添加行为 因此我不需要数百个子类 我几乎已经完成了 15 个左右的被动能力装饰器 在测试中我发现
  • 使用 Laravel 4 验证多个文件上传

    如何在 Laravel 4 中验证上传文件的数组 我已将其设置为允许多个文件 并且已测试这些文件是否存在于 Input file files 数组中 但如何验证每个文件呢 这是我尝试过的 notesData array date gt In
  • 让登录更安全

    我已使用此代码进行管理员登录 仅当用户输入正确的用户名和密码时才应打开loginhome php 但后来我意识到这根本不安全 任何人都可以直接访问 mywebsite loginhome php 而无需登录 注销后 可以使用后退按钮打开 l
  • gmail 不断阻止 PHPmailer 登录

    我将在接下来的 8 小时内部署一个网站 而 Gmail 刚刚停止接受 PHPmailer 登录我的帐户 起初 它在测试过程中工作了几个小时 然后 它就停止工作了 我已经允许所有允许不太安全的应用程序从 gmail 登录 但它仍然不允许 ph
  • Laravel 从 5.6 升级到 Laravel 6

    我有一个项目https github com javedbaloch4 Laravel Booking https github com javedbaloch4 Laravel Booking发展于Laravel 5 6现在我想将其升级到
  • PHP MySQL 使用选项/选择 HTML 表单标签进行多重搜索查询

    我正在尝试使用两个搜索字段设置基本的 MySQL LIKE 搜索 我不想拥有它 所以它有多个可选搜索字段 例如if isset POST city isset POST name 我不知道如何用 HTML 来做到这一点
  • 生成大随机数 php [重复]

    这个问题在这里已经有答案了 我想使用 PHP 生成一个包含 75 个字符的数字 我到处寻找 但一无所获 除了这个 http dailycoding com tools RandomNumber aspx http dailycoding c
  • 如何从父类函数访问子类中定义的常量?

    我从 php net 看到这个例子 但 c MY CONST 仅在 5 3
  • 如何使用 php 发送服务器错误响应?

    一旦用户点击删除按钮我的 jQuery 脚本要求服务器删除所选项目 现在我想要我的php发送成功或错误响应的脚本 是否有可能触发错误回调万一该项目无法删除 Thanks 我的 jQuery 代码 ajax type post url myA
  • PHP严格标准:声明应该兼容

    我有以下类层次结构 class O Base class O extends O Base abstract class A Abstract public function save O Base obj class A extends
  • 将“php”作为 shell 脚本执行时的自定义 php.ini 文件

    我在跑php作为 shell 脚本 我不确定 shell脚本 是否正确 该文件以 usr bin php 这很好用 但 MongoDB 类没有正确加载php ini文件 具有extension mongo so 未使用 我该如何使用它tha
  • 如何在原则 2 迁移中删除外键

    我想在原则 2 迁移中删除外键 但没有 dropForeignKeyConstraint 有谁知道怎么丢掉吗 public function down Schema schema table schema gt getTable table
  • 交换关联数组中的两个项目

    Example arr array apple gt sweet grapefruit gt bitter pear gt tasty banana gt yellow 我想调换一下柚子和梨的位置 这样数组就变成了 arr array ap
  • 使用 SSL 证书验证 Web 浏览器

    是否可以使用 ssl 证书对 Web 浏览器进行身份验证 假设我在应用程序中存储私钥 有什么方法可以从浏览器读取密钥并尝试基于该私钥进行身份验证 您可以使用 SSL TLS 客户端证书身份验证来对浏览器 用户进行身份验证 服务器必须请求客户
  • 在 PHP 中撤销 Google 访问令牌

    正如标题所示 我想以编程方式撤销授予的访问令牌 即在 PHP 中 我发现这个他们的网站 https developers google com identity protocols OAuth2WebServer tokenrevoke 但
  • PHP preg_filter 返回意外的长值

    尝试在 Woocommerce 中删除标签并过滤值 但无法以正确的格式获取它 有东西有腥味 我正在使用WC gt cart gt get cart subtotal 来检索该值 在此示例中 我的值是 2 429kr 原始返回值是 span
  • 在 apache docker 容器中运行虚拟主机

    我在同一个 apache 容器中有两个 php 应用程序 我试图在端口上运行其中一个应用程序 因为它需要通过根域而不是子文件夹进行访问 我想在端口 8060 上运行应用程序 我尝试使用 apache 虚拟主机执行此操作 但它不会加载页面 h
  • 表单计算器脚本基本价格未加载 OnLoad

    我的表单中有一个计算器来计算我的下拉选项选择 function select calculate on change calc input type checkbox calculate on click calc function cal
  • Laravel 中只向登录用户显示按钮

    如果我以 John 身份登录 如何才能只显示 John 的红色按钮而不显示 Susan 的红色按钮 测试系统环境 Win10 Laravel5 4 Mysql5 7 19 table class table table responsive
  • 无法显示 Laravel 欢迎页面

    我的服务器位于 DigitalOcean 云上 我正在使用 Ubuntu 和 Apache Web 服务器 我的家用计算机运行的是 Windows 7 我使用 putty 作为终端 遵循所有指示https laracasts com ser

随机推荐

  • 关于编程语句i++与++i的区别用法

    首先我们定义一个变量i xff0c int i 61 5 xff1b 然后我们做执行printf xff08 d xff0c i 43 43 xff09 xff1b 我们会发现输出结果是5 是为什么呢 xff0c 我们要搞清楚printf
  • eclipse出现 Some character…

    原文地址 xff1a eclipse出现 Some characters cannot be mapped using 34 GBK 34 character encoding 错误 作者 xff1a 赫西尼 Window gt Profe
  • php实现二维数组转置

    arr 61 array array 1 2 3 array 4 5 6 for i 61 0 i for j 61 0 j arr1 j i 61 arr i j for k 61 0 k for l 61 0 l echo arr1 k
  • PX4在GAZEBO仿真中加载iris模型问题

    目录 1 PX4启动仿真的launch系列文件1 1 单个launch文件解读1 2 对iris模型添加相机1 3 bashrc环境变量问题 2 一些Bug2 1 我的台式机无法加载模型2 1 1 若使用 96 v1 9 2版本 96 2
  • Springboot应用中设置Cookie的SameSite属性

    转载自https springboot io t topic 2602 一 Cookie除了key和value以外有几个属性 httpOnly 是否允许js读取cookiesecure 是否仅仅在https的链接下 xff0c 才提交coo
  • TCP如何保证可靠性,TCP如何实现可靠性传输的

    tcp 如何保证可靠性 大家都知道TCP是可靠性传输协议 xff0c 既然是可靠的 xff0c 就需要解决比如包丢失了 数据被破坏了 包重复了 乱序了等等这样的问题 下面将从几个方面介绍TCP的可靠性 1 校验和 TCP每一段报文都有校验和
  • php中标准使用类的方法

  • php复选框中获取文本框、密码域、…

    复选框能够进行项目的多项选择 xff0c 浏览者在填写一些表单时 xff0c 有时需要选择多个项目 xff08 如 xff1a 兴趣爱好等 xff09 复选框一般是多个同时存在 xff0c 为了便于传值 xff0c name的名字可以定义为
  • php页面js隐藏域的运用

    好聪明 四则运算 计算矩形 请输入第二个数 请选择运算符 43 请输入长请输入宽 请输入第一个数 好聪明 四则运算 计算矩形 请输入第一个数请输入第二个数请选择运算符 43 点击按钮 xff0c 可切换不同页面
  • mysql 空值,null与not null

    可以的 原文地址 xff1a mysql 空值 xff0c null与not null 作者 xff1a 五月jks gyS mysql探究之null与not null 1 我字段类型是not null xff0c 为什么我可以插入空值 2
  • 解决Missing argument 1 for…

    原文地址 xff1a 解决Missing argument 1 for DataTest testAdd 作者 xff1a 晨风 在使用PHPUnit的DataProvider方法时 xff0c 按官方帮助文档所说编写测试脚本如下 xff1
  • 色彩 标准卡大全及配色方案

    原文地址 xff1a 色彩 标准卡大全及配色方案 作者 xff1a 刘义0 配色方案浅析 一 红色的色感温暖 xff0c 性格刚烈而外向 xff0c 是一种对人刺激性很强的色 红色容易引起人的注意 xff0c 也容易使人兴奋 激动 紧张 冲
  • php中define()函数和defined…

    原文地址 xff1a php中define 函数和defined 函数的使用 及来防止恶意调用 作者 xff1a 疯子的博客 php中define 函数和defined 函数的使用 define 用来定义常量 xff0c 常量也是全局范围的
  • __FILE__    __LINE__

    我们在写程序的时候 xff0c 总是或多或少会加入一些printf之类的语句用于输出调试信息 xff0c 但是printf语句有个很不方便的地方就是当我们需要发布程序的时候要一条一条的把这些语句删除 xff0c 而一旦需要再次调试的时候 x
  • php魔术引用

    魔术引用发生作用是在传递 GET POST COOKIE时 下面是案例 代码 1 条件 xff1a magic quotes gpc 61 off 写入数据库的字符串未经过任何过滤处理 从数据库读出的字符串也未作任何处理 数据 xff1a
  • php类中private public prot…

    原文地址 xff1a php类中private public protected 三者之间的关系 作者 xff1a 任鹏飞 public 表示全局 xff0c 类内部外部子类都可以访问 xff1b private表示私有的 xff0c 只有
  • Python和C++版本的ROS自定义消息调试

    对python和C 43 43 版本的ROS自定义消息调试 xff08 包含自己编写的父消息嵌套子消息的例子 传送门gitee链接 xff09 文章目录 对python和C 43 43 版本的ROS自定义消息调试Step1 xff1a 工程
  • php中类的全面讲解

    一 xff1a 结构和调用 实例化 xff1a class className xff0c 调用 xff1a obj 61 new className 当类有构造函数时 xff0c 还应传入参数 如 obj 61 new className
  • socket通信简介

    我们深谙信息交流的价值 xff0c 那网络中进程之间如何通信 xff0c 如我们每天打开浏览器浏览网页时 xff0c 浏览器的进程怎么与web服务器通信的 xff1f 当你用QQ聊天时 xff0c QQ进程怎么与服务器或你好友所在的QQ进程
  • php抽象类abstract与接口理解与示…

    PHP抽象类abstract的理解对于初学者来说不是非常熟悉 xff0c 我们还需要在不断的代码积累中来积累这方面的知识 其实抽象类和接口类有一部分很像 记得在哪里看见这样一句话 xff0c 抽象类就把类像的部分抽出来 xff0c 这句看上