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 相关文章推荐
Smarty结合Ajax实现无刷新留言本实例
Jan 02 PHP
PHP+.htaccess实现全站静态HTML文件GZIP压缩传输(一)
Feb 15 PHP
解析PHP中一些可能会被忽略的问题
Jun 21 PHP
PHP 如何利用phpexcel导入数据库
Aug 24 PHP
Yii把CGridView文本框换成下拉框的方法
Dec 03 PHP
php调整服务器时间的方法
Apr 03 PHP
phpMyAdmin安装并配置允许空密码登录
Jul 04 PHP
CI操作cookie的方法分析(基于helper类库)
Mar 28 PHP
PHP框架Laravel插件Pagination实现自定义分页
Apr 22 PHP
详解thinkphp实现excel数据的导入导出(附完整案例)
Dec 29 PHP
laravel框架实现为 Blade 模板引擎添加新文件扩展名操作示例
Jan 25 PHP
php字符串倒叙
Apr 01 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 htmlentities和htmlspecialchars 的区别
2008/08/18 PHP
thinkPHP的表达式查询用法详解
2016/09/14 PHP
javascript各种复制代码收集
2008/09/20 Javascript
Javascript 陷阱 window全局对象
2008/11/26 Javascript
select、radio表单回显功能实现避免使用jquery载入赋值
2013/06/08 Javascript
javascript跨域的4种方法和原理详解
2014/04/08 Javascript
5个JavaScript经典面试题
2014/10/13 Javascript
分享两段简单的JS代码防止SQL注入
2016/04/12 Javascript
javascript类型系统——undefined和null全面了解
2016/07/13 Javascript
基于HTML+CSS+JS实现增加删除修改tab导航特效代码
2016/08/05 Javascript
Bootstrap基本组件学习笔记之列表组(11)
2016/12/07 Javascript
Three.js利用dat.GUI如何简化试验流程详解
2017/09/26 Javascript
浅谈vue路径优化之resolve
2017/10/13 Javascript
详解vue2.6插槽更新v-slot用法总结
2019/03/09 Javascript
解决vue+router路由跳转不起作用的一项原因
2020/07/19 Javascript
Vue 电商后台管理项目阶段性总结(推荐)
2020/08/22 Javascript
[01:07:46]完美世界DOTA2联赛循环赛 Magma vs IO BO2第二场 11.01
2020/11/02 DOTA
[42:00]完美世界DOTA2联赛PWL S3 Phoenix vs INK ICE 第一场 12.13
2020/12/17 DOTA
讲解python参数和作用域的使用
2013/11/01 Python
Python标准库urllib2的一些使用细节总结
2015/03/16 Python
Python2.7编程中SQLite3基本操作方法示例
2017/08/09 Python
python八皇后问题的解决方法
2018/09/27 Python
Python安装pycurl失败的解决方法
2018/10/15 Python
python语言元素知识点详解
2019/05/15 Python
python识别图像并提取文字的实现方法
2019/06/28 Python
基于python实现计算两组数据P值
2020/07/10 Python
纯css3实现的竖形无限级导航
2014/12/10 HTML / CSS
缓解脚、腿和背部疼痛:Z-CoiL鞋
2019/03/12 全球购物
行政管理专业推荐信
2013/11/02 职场文书
工业设计专业自荐书
2014/06/05 职场文书
2014离婚协议书范文两篇
2014/09/15 职场文书
工程承包协议书
2014/10/20 职场文书
2014年小学辅导员工作总结
2014/12/23 职场文书
春节慰问信范文
2015/02/15 职场文书
银行求职自荐信范文
2015/03/04 职场文书
小学生读书笔记
2015/07/01 职场文书