php面向对象的方法重载两种版本比较


Posted in PHP onSeptember 08, 2008

多个函数用同一个名字,但参数表,即参数的个数或(和)数据类型可以不同,调用的时候,虽然方法名字相同,但根据参数表可以自动调用对应的函数。

PHP4 中仅仅实现了面向对象的部分的、简单的功能,而 PHP5 以后对对象的支持就强大的多了。

对于多态的实现,PHP4 只支持覆盖(override),而不支持重载(overload)。但我们可以通过一些技巧来“模拟”重载的实现。

PHP5 虽然可以支持覆盖和重载,但重载在具体实现上,和其他语言还有较大的差别。

1,在 PHP4 中“模拟”重载

试看以下代码:

<?php
//根据参数个数选择执行不同的方法(在 PHP4 中模拟"重载"(多态的一种)

class Myclass
{
function Myclass()
{
$method = "method" . func_num_args();
$this->$method();
}

function method1($x)
{
echo "method1";
}

function method2($x, $y)
{
echo 'method2';
}
}

//通过在类中的额外的处理,使用这个类对用户是透明的:
$obj1 = new Myclass('A'); //将调用 method1
$obj2 = new Myclass('B','C'); //将调用 method2
?>

以上代码中,通过在构造函数中使用 func_num_args() 函数取到参数的个数,自动执行 method1 或 method2 方法。我们可以结合函数 func_get_arg(i) 和 func_get_args() 对以上示例进行改进。

2,在 PHP5 中使用重载

先看以下示例:

<?php 
class Myclass 
{ 
public $attriable; 
public $one = "this is one"; 
public $two = "this is two"; function __construct() 
{ 
} 
function one($one) 
{ 
$this->one=$one; 
$this->attriable = $this->one; 
} 
function one($one, $two) 
{ 
$this->one=$one; 
$this->two=$two; 
$this->attriable = $this->one . $this->two; 
} 
function display() 
{ 
echo $this->attriable; 
} 
} 
$one = "this is my class"; 
$two = "Im the best"; 
$myclass = new myclass(); 
$myclass->one($one); 
$myclass->display(); 
$myclass->one($one, $two); 
$myclass->display(); 
//本例的做法,在 PHP 中是不正确的! 
?>

使用过 C++、Java、C# 重载的人,很习惯地就会写出以上的重载实现的 PHP 代码。但这在 PHP5 中是不正确的。PHP5 并不是对前述几种语言的模仿,而是有自己的一套实现方法重载的方法(是好是坏,这里不讨论)。 虽说 PHP5 的类较 PHP4 强大了许多,但是在“重载”这个问题上并没有像我们预期的那样“改善”。在“强”类型的语言中可以通过不同的参数类型来实现“重载”,比如C++、Java、C# 等。在“固定参数”传递的语言中,还可以通过参数的个数进行传递,比如 Java,但是 PHP 是弱类型语言,因此不会出现类似以上的“重载”。

PHP5 中重载可以通过 __get, __set, and __call 几个特殊方法来进行。当 Zend 引擎试图访问一个成员并没有找到时,PHP将会调用这些方法。

在以下示例中,__get和__set代替所有对属性变量数组的访问。如果必要,你还可以实现任何类型你想要的过滤。例如,脚本可以禁止设置属性值, 在开始时用一定的前缀或包含一定类型的值。__call 方法说明了你如何调用未经定义的方法。你调用未定义方法时,方法名和方法接收的参数将会传给__call方法, PHP传递__call的值返回给未定义的方法。

<?php 
class Overloader 
{ 
private $properties = array(); function __get($property_name) 
{ 
if(isset($this->properties[$property_name])) 
{ 
return($this->properties[$property_name]); 
} 
else 
{ 
return(NULL); 
} 
} 
function __set($property_name, $value) 
{ 
$this->properties[$property_name] = $value; 
} 
public function __call($method, $p) 
{ 
print("Invoking $method()<br>\n"); 
//print("Arguments: "); 
//print_r($args); 
if($method == 'display') 
{ 
if(is_object($p[0])) 
$this->displayObject($p[0]); 
else 
if(is_array($p[0])) 
$this->displayArray($p[0]); 
else 
$this->displayScalar($p[0]); 
} 
} 
public function displayObject($p) 
{ 
echo ("你传入的是个对象,内容如下:<br>"); 
print_r($p); 
echo "<hr>"; 
} 
public function displayArray($p) 
{ 
echo ("你传入的是个数组,内容如下:<br>"); 
print_r($p); 
echo "<hr>"; 
} 
public function displayScalar($p) 
{ 
echo ("你传入的是个单独变量,内容如下:<br>" . $p); 
echo "<hr>"; 
} 
} 
$o = new Overloader(); 
//调用 __set() 给一个不存在的属性变量赋值 
$o->dynaProp = "Dynamic Content"; 
//调用 __get() 
print($o->dynaProp . "<br>\n"); 
//调用 __call() 
//$o->dynaMethod("Leon", "Zeev"); 
$o->display(array(1,2,3)); 
$o->display('Cat'); 
?>

以上代码中,调用了 display() 方法,可以根据参数的类型和个数调用类中的对应的代码段,从而实现了对象方法的重载。

PHP 相关文章推荐
用PHP读取RSS feed的代码
Aug 01 PHP
查找mysql字段中固定字符串并替换的几个方法
Sep 23 PHP
php单例模式实现(对象只被创建一次)
Dec 05 PHP
PHP调用JAVA的WebService简单实例
Mar 11 PHP
使用配置类定义Codeigniter全局变量
Jun 12 PHP
CodeIgniter模板引擎使用实例
Jul 15 PHP
ThinkPHP控制器间实现相互调用的方法
Oct 31 PHP
php与Mysql的一些简单的操作
Feb 26 PHP
PHP使用第三方即时获取物流动态实例详解
Apr 27 PHP
yii2.0整合阿里云oss的示例代码
Sep 19 PHP
PHP运用foreach神奇的转换数组(实例讲解)
Feb 01 PHP
PHP自动识别当前使用移动终端
May 21 PHP
php+AJAX传送中文会导致乱码的问题的解决方法
Sep 08 #PHP
php chr() ord()中文截取乱码问题解决方法
Sep 08 #PHP
wiki-shan写的php在线加密的解密程序
Sep 07 #PHP
php单件模式结合命令链模式使用说明
Sep 07 #PHP
网友原创的PHP模板类代码
Sep 07 #PHP
php 特殊字符处理函数
Sep 05 #PHP
php include,include_once,require,require_once
Sep 05 #PHP
You might like
php图像处理函数大全(推荐收藏)
2013/07/11 PHP
php用header函数实现301跳转代码实例
2013/11/25 PHP
CodeIgniter框架提示Disallowed Key Characters的解决办法
2014/04/21 PHP
PHP判断上传文件类型的解决办法
2015/10/20 PHP
PHP常用算法和数据结构示例(必看篇)
2017/03/15 PHP
Laravel框架实现定时发布任务的方法
2018/08/16 PHP
thinkPHP5.1框架使用SemanticUI实现分页功能示例
2019/08/03 PHP
De facto standard 世界上不可思议的事实标准
2010/08/29 Javascript
学习javascript,实现插入排序实现代码
2011/07/31 Javascript
javascript模块化是什么及其优缺点介绍
2013/09/02 Javascript
javascript框架设计读书笔记之字符串的扩展和修复
2014/12/02 Javascript
PHP中CURL的几个经典应用实例
2015/01/23 Javascript
jQuery读取XML文件内容的方法
2015/03/09 Javascript
jquery实现上传文件大小类型的验证例子(推荐)
2016/06/25 Javascript
Javascript实现登录记住用户名和密码功能
2017/03/22 Javascript
微信小程序实现给循环列表添加点击样式实例
2017/04/26 Javascript
详解前端路由实现与react-router使用姿势
2017/08/07 Javascript
Gulp实现静态网页模块化的方法详解
2018/01/09 Javascript
小程序富文本提取图片可放大缩小
2020/05/26 Javascript
[01:19]2014DOTA2国际邀请赛 采访TITAN战队ohaiyo 能赢DK很幸运
2014/07/12 DOTA
[01:52]PWL S2开团时刻第四期——DOTA2成语故事
2020/12/03 DOTA
python 字典中文key处理,读取,比较方法
2018/07/06 Python
python读取和保存图片5种方法对比
2018/09/12 Python
Tensorflow的常用矩阵生成方式
2020/01/04 Python
Python 实现自动登录+点击+滑动验证功能
2020/06/10 Python
个人简历的自荐信
2013/10/23 职场文书
交通法规咨询中心工作职责
2013/11/27 职场文书
经济管理专业毕业生自荐信范文
2014/01/02 职场文书
大二自我鉴定
2014/01/31 职场文书
军校大学生个人的自我评价
2014/02/17 职场文书
机电职业生涯规划书范文
2014/03/08 职场文书
2014年班级工作总结范文
2014/12/23 职场文书
幼儿园班级工作总结2015
2015/05/25 职场文书
pytest进阶教程之fixture函数详解
2021/03/29 Python
Java用自带的Image IO给图片添加水印
2021/06/15 Java/Android
Pandas搭配lambda组合使用详解
2022/01/22 Python