2010-03-13 75 views
2

这里是我的代码是什么样子PHP和类:获得父母的公共财产父类中

我有两种形式:

class Form_1 extends Form_Abstract { 

    public $iId = 1; 

} 
class Form_2 extends Form_1 { 

    public $iId = 2; 

} 

我期待的代码这样的表现:

$oForm = new Form_2; 
echo $oForm->getId(); // it returns '2' 
echo $oForm->getParentId(); // i expect it returns '1' 

这里是我的Form_Abstract类:

class Form_Abstract { 

    public $iId = 0; 

    public function getId() { 
     return $this->iId; 
    } 

/** 
this method will be called from a child instance 
*/ 
    public function getParentId() { 
     return parent::$iId; 
    } 
} 

但它抛出一个致命错误:

Fatal error: Cannot access parent:: when current class scope has no parent 

请帮助我的方法getParentId()

PS:我知道发生了什么,我寻求解决方案的原因。

+0

你实际想要在这里实现的目标是什么?换句话说:“Form_1”和“Form_2”之间的实际函数关系是什么。很可能你的设计需要重新思考。例如,您可能需要一个聚合/复合对象或其他设计范例,而不是使用继承。 – 2010-03-13 17:18:35

回答

5

您必须使用Reflection Api才能访问父类的属性默认值。替代getParentId,在Form_Abstract,这一点,和一切工作正常:

public function getParentId() { 
    $refclass = new ReflectionClass($this); 
    $refparent = $refclass->getParentClass(); 
    $def_props = $refparent->getDefaultProperties(); 

    return $def_props['iId']; 
} 

显然,你不能在根类调用getParentId(),所以最好检查是否父类存在。

UDATE:

你可以做同样的类/对象功能:

public function getParentId() { 
    $def_values = get_class_vars(get_parent_class($this)); 
    return $def_values['iId']; 
} 
+0

它的工作。谢谢,你对代码性能的看法是什么? – Alexar 2010-03-13 17:49:29

+0

我不知道。但是,使用类/对象函数应该比反射快。一般来说,反射速度不是很快,所以只有在没有其他“正确”的方法来实现你想要的时候,仔细反思。 然而,这取决于你如何使用它。 – 2010-03-13 18:07:44

+0

我做了一些粗略的基准测试,在这个简单的例子中,性能似乎不成问题。例如,通过拨打数百万的电话,我的第二个getparentid版本和getId()一样快。带反射的版本速度只有10% – 2010-03-13 18:58:01

1

我不认为甚至可以访问“父级”的$iId版本:您实际上并没有在子类中重新定义它:您只有在父级的定义值类。

为了使事情变得非常简单:当你声明Form_2extends Form_1,它需要所有的属性和方法Form_2,并把它们放在Form_1,覆盖了已经存在那里。
不再有“两个不同的类别”:只有一个结果对象,同时是Form_1Form_2


这里有一个例子那种 - 我希望 - 将帮助明白我的意思:

class Form_Abstract {} 
class Form_1 extends Form_Abstract { 
    public $iId = 1; 
    public function methodInParent() { 
     var_dump($this); 
    } 
} 
class Form_2 extends Form_1 { 
    public $iId = 2; 
    public function tryingToGetParentProperty() { 
     var_dump(parent::$iId); 
    } 
} 

$form2 = new Form_2(); 
$form2->methodInParent(); 
$form2->tryingToGetParentProperty(); 


使用这个代码部分,调用$form2->methodInParent()会得到你:

object(Form_2)#1 (1) { 
    ["iId"]=> 
    int(2) 
} 

即即使调用/执行父级的定义的方法$iId属性仍然是孩子定义的值类:该属性有一个且只有一个版本!


而调用$form2->tryingToGetParentProperty()将让你:

Fatal error: Access to undeclared static property: Form_1::$iId 

由于没有static财产称为$iIdForm_1


我想一个解决方案,以避免这种情况将宣布$iIdstatic - 但请注意,它会改变你的代码的含义,它的行为方式!

static变量将在班级的所有实例中共享 - 这可能不是您想要的^^

+0

谢谢你的回答,但我不接受它,因为在一个类中可以访问parent :: someMethod(),所以我认为这可能是一种方式来访问父:: $ someVar – Alexar 2010-03-13 17:15:29

+0

谢谢,请注意parent :: $ someVar并不意味着静态变量。它是PHP语法。 – Alexar 2010-03-13 17:35:46

+0

不客气:-) ;;;好吧,但致命的错误,我说*“访问未声明的静态属性”* - 没有多少我可以做的那^^ – 2010-03-13 17:40:20

3

错误是因为您正在调用没有父级的类的父级(它没有扩展一个现有的类)。

+0

我知道,但我的对象是Form_2而不是Form_Abstract – Alexar 2010-03-13 17:11:48

+0

当然,但父母没有解决运行时间,所以你仍然处于抽象的上下文中。 – Macmade 2010-03-13 17:15:33

+0

好吧,也许。所以你的解决方案是什么? – Alexar 2010-03-13 17:16:58

0

我做到了这个工作:

public function getParentId() { 
    $sClass = get_parent_class($this); 
    $tmp = new $sClass; 
    return $tmp->iId; 
} 

但它是一个标准的解决方案,它是否有任何性能问题

+2

这是一个非常糟糕的主意,因为你只是为了获得一个属性而创建一个新实例......例如,如果你的类在实例化时连接到数据库,例如? – Macmade 2010-03-13 18:07:05

+1

对于性能,我已经做了一些粗略的基准测试,其中有几百万次getparentid调用,而您的版本和我的版本(使用反射API和类对象函数)同样快。所以我认为在这种简单的情况下,性能不是问题。 我不喜欢太实例化一个类只有默认值,它不是一个漂亮的代码。 – 2010-03-13 18:44:39

+0

Macmade是正确的,这样你就可以依赖于构造函数的作用,每次调用构造函数时,都不能认为它是“标准”解决方案 – 2010-03-13 19:02:18