在PHP

时间:2017-06-07 15:23:13

标签: php reflection

这是我的测试代码:

class Base
{
    public $property;

    public function method() {
        return 456;
    }

    public function setProperty($value) {
        $this->property = $value;
    }
}

class Derived extends Base
{
    public function method() {
        return 789;
    }
}

$derived = new Derived;
$derived->setProperty(123);

$base = getParentInstance($derived);

echo $base->property; // Should print 123
echo $base->method(); // Should print 456

环顾四周,我发现很多相关的东西,但没有直接到达目的。我只需要将一个实例转换为祖先类。这甚至可以在PHP上使用吗?

到目前为止,我出现了这个错误的代码(我认为)只是实例化一个新的Base类:

function getParentInstance($object)
{
    $reflection = new ReflectionObject($object);
    $parent_class = $reflection->getParentClass();
    return $parent_class->newInstanceWithoutConstructor();
}

另一个复杂因素是我只能修改Derived ... Base由外部框架提供。

附录

以下是我要求的证据并非荒谬。 C ++中的相同代码:

class Base
{
public:
    int property;

    int method() {
        return 456;
    }

    void setProperty(int value) {
        this->property = value;
    }
};

class Derived: public Base
{
public:
    int method() {
        return 789;
    }
};

#include <iostream>
int main()
{
    Derived *derived = new Derived;
    derived->setProperty(123);

    Base *base = (Base *) derived; // Is **this** possible in PHP?

    std::cout << base->property; // It prints 123
    std::cout << base->method(); // It prints 456

    return 0;
}

3 个答案:

答案 0 :(得分:1)

正如许多人提到的,你不应该这样做,从技术上讲,你不能这样做。

您可以模拟行为以获得您期望的结果:

class Derived extends Base
{
    protected $isProxy = false;

    public function method() {
        return $this->isProxy ? parent::method() : 'def';
    }

    /**
     * not really a parent. The same class, which behave like a parent in this specific case
     */    
    public function getParent()
    {
      $this->isProxy = true;
      $base = clone $this;
      $this->isProxy = false;
      return $base;
    }
}

$derived = new Derived;
$derived->setProperty(123);

$base = $derived->getParent();

echo $base->property; // prints 123
echo $base->method(); // prints 456

修改

您可以做的其他事情的简化示例:

function getParentInstance($child) {
  $base = new Base();
  $base->property = $child->property;
  return $base;
}

这仅适用于公共属性。 应使用Reflection访问/分配私有/受保护的属性。

答案 1 :(得分:0)

你对一些OOP例程感到困惑。您已经将所有父实例放入子类中,如果要将范围关闭到避免多态的范围,则只需定义特定方法:

class Base
{
    public $property;

    public function method() {
        return 456;
    }

    public function setProperty($value) {
        $this->property = $value;
    }
}

class Derived extends Base
{
    public function method($parent = false) {
        return ($parent) ? parent::method() : $this->property;
    }
}

$derived = new Derived;
$derived->setProperty(123);
echo $derived->method(); // Should print 123
echo $derived->method(true); // Should print 456

答案 2 :(得分:0)

我想把它放在这里,因为它可以回答这个问题。虽然没有实例化的Base对象,但您仍然可以通过php parent访问父数据。

我不是100%确定这里的尝试是什么,但你可以像

一样使用它
//No changes to Base

class Derived extends Base {
    public function method($p=false) {//Adding a flag
        if($p){// true mean you want the parent method
            return parent::method(); //Use parent:: to call that method
        } else { //False do your own thing
            return 'def';
        }
    }
}

$derived = new Derived;

$derived->setProperty(123);

echo $derived->property; // Print 123

echo $derived->method(); // Prints def

echo $derived->method(false); // Prints def

echo $derived->method(true); // Prints 456

这很奇怪,但至少可以达到预期的一种方式。

此外,最简单的方法是在父母和孩子的功能不同时不覆盖您的父method

//No changes to Base

class Derived extends Base {
    public function child_method() {
        return 'def';
    }
}

$derived = new Derived;

$derived->setProperty(123);

echo $derived->property; // Print 123

echo $derived->method(); // Prints 456

echo $derived->child_method(false); // Prints def