php中模拟多继承如何实现
php中模拟多继承如何实现
一、总结
一句话总结:其实你继承别人也是想调用别人类里面的方法和属性,所以可以这样做:这本类中创建目标类的对象,然后通过这个对象来调用方法和属性,这样比继承来的方便。
二、魔术方法 __call 实现模拟多继承
1、相关知识
PHP没有多继承的特性。即使是一门支持多继承的编程语言,我们也很少会使用这个特性。在大多数人看来,多继承不是一种好的设计方法。想要给某个类添加额外的特性,不一定要使用继承。这里我提供一种模拟多继承的方法以供参考。
PHP有一个魔术方法,叫做__call。当你调用一个不存在的方法时,这个方法会被自动调用。这时,我们就有机会将调用重定向到一个存在的方法。继承多个父类的子类,寻找方法的过程一般是这样的:
本身的方法 -> 父类1的方法 -> 父类2的方法...
模拟过程大致是这样:将各个父类实例化,然后作为子类的属性。这些父类提供一些公有的方法。当子类拥有某方法时,__call()函数不会被调用。这相当于“覆盖”了父类的方法。当调用了不存在的方法时,通过__call()方法依次从父类中寻找可以调用的方法。虽然这不是完备的多继承,但可以帮助我们解决问题。
<?php
class Parent1 {
function method1() {}
function method2() {}
}
class Parent2 {
function method3() {}
function method4() {}
}
class Child {
protected $_parents = array();
public function Child(array $parents=array()) {
$_parents = $parents;
} public function __call($method, $args) {
// 从“父类"中查找方法
foreach ($this->_parents as $p) {
if (is_callable(array($p, $method))) {
return call_user_func_array(array($p, $method), $args);
}
}
// 恢复默认的行为,会引发一个方法不存在的致命错误
return call_user_func_array(array($this, $method), $args);
}
}
$obj = new Child(array(new Parent1(), new Parent2()));
$obj->method1();
$obj->method3();
这里没有涉及属性的继承,但实现起来并不困难。可以通过__set()和__get()魔术方法来模拟属性的继承。请你动手实践。
其它方法:通过接口来实现多继承
php中的类只能继承一个父类,如果要继承多个类应采用接口
interface 模拟多继承
三、PHP接口实现多继承详解
在PHP的接口中,接口可以继承接口。虽然PHP类只能继承一个父类(单继承),但是接口和类不同,接口可以实现多继承,可以继承一个或者多个接口。当然接口的继承也是使用extends关键字,要多个继承的话只要用逗号把继承的接口隔开即可。
需要注意的是当你接口继承其它接口时候,直接继承父接口的静态常量属性和抽象方法,所以类实现接口时必须实现所有相关的抽象方法。
现在你对PHP接口的继承有所了解了吧,下面的例子可供参考,代码如下:
- <?php
- interface father{
- function shuchu();
- }
- interface fam extends father{
- function cook($name);
- }
- class test implements fam{
- function shuchu(){
- echo "接口继承,要实现两个抽象方法";
- echo "<br>";
- }
- function cook($name){
- echo "平时经常做饭的人是:".$name;
- }
- }
- $t=new test();
- $t->shuchu();
- $t->cook("妈妈");
- ?>
代码运行结果如下:
接口继承,要实现两个抽象方法 平时经常做饭的人是:妈妈 |
上面的示例是接口继承了一个接口,所以在test类实现fam接口的时候要实例两个抽象方法,就是把接口的子类和父类的抽象方法都实例。
下面来看一个接口多继承的示例,代码如下:
- <?php
- interface father{
- function shuchu();
- }
- interface mother{
- function dayin($my);
- }
- interface fam extends father,mother{
- function cook($name);
- }
- class test implements fam{
- function dayin($my){
- echo "我的名字是:".$my;
- echo "<br>";
- }
- function shuchu(){
- echo "接口继承,要实现两个抽象方法";
- echo "<br>";
- }
- function cook($name){
- echo "平时经常做饭的人是:".$name;
- }
- }
- $t=new test();
- $t->shuchu();
- $t->dayin("小强");
- $t->cook("妈妈");
- ?>
示例运行结果:
接口继承,要实现两个抽象方法 我的名字是:小强 平时经常做饭的人是:妈妈 |
这段代码由于接口继承了两个接口,所有实例时要把这三个抽象类的所有抽象方法都实例,总共有三个。看完这两个例子,你应该对接口的继承熟悉了吧,其实就一个单继承和多继承,只要实现了所有相关的抽象方法就可以了。
php中模拟多继承如何实现的更多相关文章
- js模拟实现继承功能
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- iOS开发·runtime原理与实践: 消息转发篇(Message Forwarding) (消息机制,方法未实现+API不兼容奔溃,模拟多继承)...
本文Demo传送门: MessageForwardingDemo 摘要:编程,只了解原理不行,必须实战才能知道应用场景.本系列尝试阐述runtime相关理论的同时介绍一些实战场景,而本文则是本系列的消 ...
- JS中的原型继承机制
转载 http://blog.csdn.net/niuyongjie/article/details/4810835 在学习JS的面向对象过程中,一直对constructor与prototype感到很 ...
- C#中是否可以继承String类
C#中是否可以继承String类? 答:String类是sealed类故不可以继承. 当对一个类应用 sealed 修饰符时,此修饰符会阻止其他类从该类继承. 在下面的示例中,类 HoverTree ...
- 理解JavaScript中的原型继承(2)
两年前在我学习JavaScript的时候我就写过两篇关于原型继承的博客: 理解JavaScript中原型继承 JavaScript中的原型继承 这两篇博客讲的都是原型的使用,其中一篇还有我学习时的错误 ...
- C#中事件的继承
C#中的子类无法调用父类的事件,可以通过在父类中创建一个方法来调用父类的事件,而子类通过调用父类的方法来触发事件. class parent { protected string name; publ ...
- C++中的虚继承 & 重载隐藏覆盖的讨论
虚继承这个东西用的真不多.估计也就是面试的时候会用到吧.. 可以看这篇文章:<关于C++中的虚拟继承的一些总结> 虚拟基类是为解决多重继承而出现的. 如:类D继承自类B1.B2,而类B1. ...
- python中使用多继承
python中使用多继承,会涉及到查找顺序(MRO).重复调用(钻石继承,也叫菱形继承问题)等 MRO MRO即method resolution order,用于判断子类调用的属性来自于哪个父类.在 ...
- 如何在C#中模拟C++的联合(Union)?[C#, C++] How To Simulate C++ Union In C#?
1 什么是联合? 联合(Union)是一种特殊的类,一个联合中的数据成员在内存中的存储是互相重叠的.每个数据成员都在相同的内存地址开始.分配给联合的存储区数量是“要包含它最大的数据成员”所需的内存数. ...
随机推荐
- Jenkins学习总结(2)——Jenkins+Maven进行Java项目持续集成
最近配置了Jenkins服务器,记录下基本过程.(当然还遇到了若干小问题,兵来将挡水来土掩就是了) Jenkins安装 安装Tomcat 从Jenkins官网下载jenkins.war文件.官网地址: ...
- 浅谈架构之路:单点登录 SSO
前言:SSO 单点登录 "半吊子"的全栈工程师又来了,技术类的文章才发表了两篇,本来想先将主攻的几个系列都开个头(Nodejs.Java.前端.架构.全栈等等),无奈博客起步太晚, ...
- AngularJS渲染性能分析
作者:Jiang, Jilin AngularJS中,通过数据绑定.能够十分方便的构建页面.可是当面对复杂的循环嵌套结构时,渲染会遇到性能瓶颈.今天,我们将通过一些列实验,来測试AngularJS的渲 ...
- shell-手机屏幕录制
今天在做android联系的时候,想要把自己写的demo效果记录下来.在网上发现了录制手机屏幕的方法,如下 adb shell screenrecord /sdcard/demo.mp4 解释 adb ...
- actionBar-shareIcon 分享按钮的修改
今天为了修改图库的分享按钮,进行了很多的尝试 1.寻找到了xml文件,如下 <?xml version="1.0" encoding="utf-8"?&g ...
- php函数按地址传递参数(php引用)
php函数按地址传递参数(php引用) 一.总结 1.php引用:php引用和c++一样,都是在变量前加&(取地址符号) 2.php函数按地址传递参数:php函数按地址传递参数(php引用)也 ...
- make 2>&1 | tee build.log
make 2>&1 | tee build.log 保存编译log,方便问题查找
- 使IIS服务器支持下载 apk/ipa 安装包
默认情况下,使用IIS作为Web服务器的无法下载此文件,访问会触发404错误,服务器找不到对应资源. IIS服务器不能下载.apk文件的原因:iis的默认MIME类型中没有.apk文件,所以无法下载. ...
- BZOJ1030: [JSOI2007]文本生成器(Trie图+dp)
Description JSOI交给队员ZYX一个任务,编制一个称之为“文本生成器”的电脑软件:该软件的使用者是一些低幼人群,他们现在使用的是GW文本生成器v6版.该软件可以随机生成一些文章―――总是 ...
- SQLITE数据表主键设置Id自增方法
SQLITE数据表主键设置Id自增方法 标签: sqliteintegerinsertnulltableapi 2010-01-12 08:39 35135人阅读 评论(8) 收藏 举报 分类: S ...