代码之家  ›  专栏  ›  技术社区  ›  Fluffy

PHP:扩展现有类

  •  1
  • Fluffy  · 技术社区  · 14 年前

    是否可以设置类的父级?例如,在运行时实例化父类的实例,然后创建扩展某个父实例的子类实例。例如:

    class A {
        var $test = 'default';
    }
    
    class B extends A {
        public function __contsruct(A $a) {
            parent = $a; //does not work
        }
    }
    
    $a = new A();
    $a->test = 'changed';
    $b = new B($a);
    $b->test == 'changed'; //should be true
    

    $b = new B(); $b->test = 'changed' ,但这不是我要问的。

    3 回复  |  直到 12 年前
        1
  •  1
  •   Charles    14 年前

    您所要求的在基本PHP中是不可能的。有几种方法可以做类似的事情。

    你可以用高度实验性的 runkit 分机。这个 runkit_class_emancipate runkit_class_adopt

    runkit_method_add 相关功能可能更合适。不过,它仍然在整个类上运行。

    __call . 事实上 anonymous functions 在5.3中,你可以做一些像。。。

    class Bar {
        public function say($thing) {
            echo "Bar::say says: $thing\n";
        }
    }
    
    class Foo extends Bar {
        private $extensions = array();
    
        public function addExtension($func_name, $func) {
            $this->extensions[ $func_name ] = $func;
        }
    
        public function __call($func_name, $arguments) {
            array_unshift($arguments, $this);
            if(array_key_exists($func_name, $this->extensions))
                call_user_func_array($this->extensions[ $func_name ], $arguments);
        }
    }
    
    $f = new Foo();
    $anon = function($obj, $string){ $obj->say($string); };
    $f->addExtension('example', $anon);
    $f->example("Hello, world!");
    

    $this . 这也意味着它们不能引用类的受保护或私有成员。可以通过克隆实例并使用 Reflection 暴露受保护的和私有的成员。看到了吗 this comment on the anonymous function manual page

    由于PHP的限制,您不能直接将匿名函数分配给属性并调用它。这个例子行不通:

    class WillNotWork {
        public $fatal_error;
    }
    
    $broken = new WillNotWork();
    $anon = function($arg) { echo "I'm about to create a {$arg} error!"; };
    $broken->fatal_error = $anon;
    $broken->fatal_error("fatal");
    // Fatal error: Call to undefined method WillNotWork::fatal_error()
    
        2
  •  2
  •   bur    12 年前

    class Foo
    {
        function __construct() {
            $this->hello = "Hello";
        }
    
        public function sayHello() {
            echo $this->hello."!";
        }
    }
    
    class Bar
    {
        function __construct(&$foo) {
            $this->foo = $foo;
        }
    
        public function sayHelloAgain() {
            echo $this->foo->sayHello()." Again!";
        }
    }
    
    $foo = new Foo();
    echo $foo->sayHello(); //outputs "Hello!"
    
    $bar = new Bar($foo);
    echo $bar->sayHelloAgain(); //outputs "Hello! Again!"
    
        3
  •  0
  •   Chris Bier    12 年前

    不,因为 $a 是一个单独的实例 $b .