PHP重载和多态的实现?

PHP重载和多态的实现?大家给说说吧

评论 (0)链接2012-01-17 

重载:即在子类中对于父类中的方法进行重新定义。比如在父类中有一个 hello 的方法,那么在子类中,可以对hello 进行重新定义。
多态的话,则一个接口实现不同的输出。一般在策略模式中使用,如下载一个文件的话。虽然同是下载,但是可以给其定义不同系统上的下载方法。如linux下可能下到.zip的文件,而windows下到rar的文件

该答案已被锁定,无法对其进行评论,编辑及投票。
()
评论 (1)链接 • 2012-01-17
  • 0 支持
    您这个讲的应该是重写(overwrite)而不是重载(overload)吧 – 刘洋1986 2013-05-03

答案中方法有写代码是转载,呵呵~~~~~
1.重载的实现:
方法1:用__call()方法

今天遇到一个头疼的问题,如何在PHP中实现方法重载(包括构造器重载).查阅了很多资料,直接重载是无法实现的.但是可以通过__call()方法来变相实现.实际上这个方法我认为很差.是PHP开发者偷懒,才想出这么一个拐弯抹角的方法,而且用这个方法实现的重载程度非常有限,尤其是构造器重载,已经不是真正意义上的构造器。构造器在对象被创建时自动执行,一般不会显式的调用。而用__call()方法实现的构造器必须显示的调用,也就是说构造函数与普通函数的性质完全相同,只不过功能不同而已了。
下面是我写出的一个实例代码:
<?php
class OverloadTest{

  
public function __call($name,$para){

if($name=='construct'){
switch (count($para)){
case 0:

  
$this->cons1();
break;

case 1:

  
$this->cons2($para[0]);
break;

default:

  
print "wrong para";

}
}else{
print 'Undefined method '.$name;
}

  
}
function cons1(){

echo "cons1() called";

  
}
function cons2($var){

echo "cons2() called.";

}
$foo = new OverloadTest();
$foo->construct();
$foo->construct('test');
?>

定义了类OverloadTest,目的是使该类有两个构造器,一个是无参数的,一个是有一个参数的(普通method的重载与这个道理完全相同)。由于无法直接定义两个__construct()构造器,因此只好定义cons1()和cons2($var)两个普通方法,然后定义__call()方法,在__call()方法中判断调用的来源,如果是调用construct()函数,则根据参数的个数情况分别转到不同的方法去执行。如参数个数为0时,转到cons1(),参数个数为1时,转到cons2()。还可以继续增加所支持的参数的个数,只需要在switch---case 语句中增加即可。另外如果有足够的精力,还可以通过使用is_int()等函数来判断参数的类型,进而可以根据不同的参数类型调用不同的方法。

细节代码不再赘述,有问题的可以到群中讨论。

方法2:用func_get_args()和func_num_args()函数

func_get_args()和func_num_args()函数以前没大用过。今天受phpdream朋友的启发,研究了一下这两个函数的功能,发现可以很好的解决方法重载的参数传递问题。尤其是采用这种方法后,构造器的问题得到了较好的解决,可以不必显式的调用构造器,这一点非常不错。普通的方法重载,也可以用这个方法很好的实现。
一个完整的实例如下:(以构造器重载为例)
<?php
class OverloadTest{
function __construct(){
$arr=func_get_args();
switch(func_num_args()){
case 1:
$this->cons1($arr[0]);
break;
case 2:
$this->cons2($arr[0],$arr[1]);
break;
}
}

  
function cons1($var){

echo "cons1(".$var.") called.";

function cons2($var1,$var2){
echo "cons2(".$var1.",".$var2.") called.";

}
$foo = new OverloadTest('x');
$foo2 = new OverloadTest('x',"y");

?>
根据我的实验,这种情况下有可能出现PHP警告,原因是参数个数不匹配,但是我在PHP5+APACHE2下测试,打开所有的error_reporting,仍然没有任何警告信息。但是为了保险起见,我建议在调用重载的方法前在语句前加“@”,来防止出现警告信息。如本例中,可以这样:
@$foo = new OverloadTest('x');
@$foo2 = new OverloadTest('x',"y");
如果是调用普通方法
@$var=method1();
@$var2=method1('xyz');

2.多态的实现:
PHP 5.x 虽然支持抽象类和接口, 但并不支持多态,那如何实现多态呢?可以借助接口来实现。
1. 建立 ITest.php 接口
< ?php
interface ITest
{

  
public function test($a, $b);

}
?>
2. 建立 TestLibary 文件夹, 在这个文件夹下定义的所有类都实现 ITest 接口, 以下是一些例子。
PerformanceTest.php

<?php
class PerformanceTest implements ITest
{
public function __construct()
{
//构造方法

public function test($a, $b)
{
//接口方法的实现
echo '我是 PerformanceTest 类';

}
DataTest.php

<?php
class DataTest implements ITest
{
public function __construct()
{
//构造方法

public function test($a, $b)
{
//接口方法的实现
echo '我是 DataTest 类';

}

薛帮书
编辑于 2012-01-17
该答案已被锁定,无法对其进行评论,编辑及投票。
()
评论 (0)链接 • 2012-01-17

PHP 对父方法的重写很郁闷,必须参数保持一致,建议 如果父类某个方法在子类有可能被重写的话,父类方法定义时最好不带参数定义,子类覆盖时在方法里面可以使用 func_get_args() 来获取参数,重写不同的功能

该答案已被锁定,无法对其进行评论,编辑及投票。
()
评论 (0)链接 • 2012-01-17

重载及方法的覆盖是多态的两种实现方式...你的问题好奇怪

该答案已被锁定,无法对其进行评论,编辑及投票。
()
评论 (0)链接 • 2013-05-03
德问是一个专业的编程问答社区,请 登录注册 后再提交答案