当前位置:  开发笔记 > 编程语言 > 正文

重新定义类方法或类

如何解决《重新定义类方法或类》经验,为你挑选了6个好方法。

有没有办法在不使用典型继承的情况下重新定义类或其某些方法?例如:

class third_party_library {
    function buggy_function() {
        return 'bad result';
    }
    function other_functions(){
        return 'blah';
    }
}

我该怎么做才能取代buggy_function()?显然这就是我想做的

class third_party_library redefines third_party_library{
    function buggy_function() {
        return 'good result';
    }
    function other_functions(){
        return 'blah';
    }
}

这是我的两难:我更新了破坏我代码的第三方库.我不想直接修改库,因为将来的更新可能会再次破坏代码.我正在寻找一种无缝的方法来替换类方法.

我发现这个图书馆说它可以做到,但我很谨慎,因为它已经4岁了.

编辑:

我应该澄清一下,由于框架限制,我无法将类重命名third_party_librarymagical_third_party_library或其他任何内容.

为了我的目的,是否可以只在类中添加一个函数?我认为你可以用C#做​​一个叫做"部分类"的东西.



1> Jonathan Lon..:

它被称为猴子修补.但是,PHP没有本机支持.

虽然,正如其他人也指出的那样,runkit库可用于添加对该语言的支持,并且是classkit的继承者.而且,虽然它的创建者似乎已经放弃了(虽然声称它与PHP 5.2及更高版本不兼容),但该项目现在似乎有了一个新的家和维护者.

我仍然不能说我是它的方法的粉丝.通过评估代码串进行修改在我看来总是有潜在危险并且难以调试.

仍然,runkit_method_redefine似乎是您正在寻找的,并且可以/tests/runkit_method_redefine.phpt在存储库中找到它的使用示例:

runkit_method_redefine('third_party_library', 'buggy_function', '',
    'return \'good result\''
);



2> 小智..:

runkit似乎是一个很好的解决方案,但默认情况下它没有启用,部分仍然是实验性的.所以我一起攻击了一个小类,它取代了类文件中的函数定义.用法示例:

class Patch {

private $_code;

public function __construct($include_file = null) {
    if ( $include_file ) {
        $this->includeCode($include_file);
    }
}

public function setCode($code) {
    $this->_code = $code;
}

public function includeCode($path) {

    $fp = fopen($path,'r');
    $contents = fread($fp, filesize($path));
    $contents = str_replace('','',$contents);
    fclose($fp);        

    $this->setCode($contents);
}

function redefineFunction($new_function) {

    preg_match('/function (.+)\(/', $new_function, $aryMatches);
    $func_name = trim($aryMatches[1]);

    if ( preg_match('/((private|protected|public) function '.$func_name.'[\w\W\n]+?)(private|protected|public)/s', $this->_code, $aryMatches) ) {

        $search_code = $aryMatches[1];

        $new_code = str_replace($search_code, $new_function."\n\n", $this->_code);

        $this->setCode($new_code);

        return true;

    } else {

        return false;

    }

}

function getCode() {
    return $this->_code;
}
}

然后包括要修改的类并重新定义其方法:

$objPatch = new Patch('path_to_class_file.php');
$objPatch->redefineFunction("
    protected function foo(\$arg1, \$arg2)
    {   
        return \$arg1+\$arg2;
    }");

然后评估新代码:

eval($objPatch->getCode());

有点原油,但它的工作原理!



3> Till..:

为了完整起见 - 通过runkit在PHP中提供了猴子补丁.有关详情,请参阅runkit_method_redefine().



4> 小智..:

如何将它包装在另一个类中

class Wrapper {
 private $third_party_library;
 function __construct() { $this->third_party_library = new Third_party_library(); }
 function __call($method, $args) {
  return call_user_func_array(array($this->third_party_library, $method), $args);
 }
}



5> Ludo - Off t..:

对于那些仍在寻找这个答案的人.

您应该将extends与名称空间结合使用.

像这样:

namespace MyCustomName;

class third_party_library extends \third_party_library {
  function buggy_function() {
      return 'good result';
  }
  function other_functions(){
      return 'blah';
  }
}

然后使用它做这样:

use MyCustomName\third_party_library;

$test = new third_party_library();
$test->buggy_function();
//or static.
third_party_library::other_functions();



6> Till..:

是的,它被称为extend:



我以"sd"为前缀.;-)

请记住,当您扩展类以覆盖方法时,方法的签名必须与原始方法匹配.因此,例如,如果原始说buggy_function($foo, $bar),它必须匹配扩展它的类中的参数.

PHP非常冗长.


那么答案是,你做不到.
OP询问如何"没有典型的继承".即他正在寻找类似Java的反思
这通常会起作用,但由于我正在使用的框架是如何设置的,我无法更改类名
推荐阅读
coco2冰冰
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有