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)是一种特殊的类,一个联合中的数据成员在内存中的存储是互相重叠的.每个数据成员都在相同的内存地址开始.分配给联合的存储区数量是“要包含它最大的数据成员”所需的内存数. ...
随机推荐
- 002 python介绍/解释器安装/变量/常量/内存管理
编程语言介绍 机器语言 :直接用计算机二进制指令编写程序,直接控制硬件 汇编语言:用英文标签取代二进制指令编写程序,本质也是直接控制硬件 高级语言:用人能理解的表达方式来编写程序,无需考虑硬件的操作细 ...
- 用内置的库turtle来画一朵花,python3
题目:用内置的库turtle来画一朵花 看了群主最后成像的图片,应该是循环了36次画方框,每次有10度的偏移. 当然不能提前看答案,自己试着写代码. 之前有用过海龟画图来画过五角星.奥运五环.围棋盘等 ...
- 【MongoDB】mongodump and mongorestore of mogodb
The another tool will be mentioned in this blog, namely mongodump and mongorestore. General speaking ...
- ZOJ 3587 Marlon's String 扩展KMP
链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3587 题意:给出两个字符串S和T.S,T<=100000.拿出 ...
- Monkey测试执行指导
1.Monkey常规测试
- 1.字符设备驱动------Linux中断处理体系结构
一.中断处理体系结构的初始化 Linux内核将所有的中断统一编号,使用一个irq_desc结构数组来描述这些中断;每个数组项对应一个中断,也可能是一组中断,它们共用相同的中断号,里面记录了中断的名称. ...
- LAN8720A网络模块的使用问题
一.LAN8720A模块驱动电路 最近在调试STM32F4驱动LAN8720A网络模块,在做方案前参考是正点原子的LAN8720A的驱动电路方案,但是从网上买回来的LAN8720A模块用正点原子的例程 ...
- Redis .Net客户端源码
1.简单介绍 当前NoSql使用已经极为普遍,无论是Java生态圈,还是.net生态圈.大大小小的Web站点在追求高性能高可靠性方面,不由自主都选择了NoSQL技术作为优先考虑的方面.主流的技术有:H ...
- 11.typeid
#include <iostream> using namespace std; void main() { int a; cout << typeid(a).name() & ...
- android 4.4 添加物理按键
kernel下添加 Linux-3.4/drivers/input/keyboard/Makefile linux-3.4/drivers/input/keyboard/sw-keyboard.c s ...