php中的父对象
是否有方法遍历对象以获取父对象数据? “父对象”不是指父类,而是字面上的对象。 这里有一个例子,在javascripty世界中:-): 如果我可以访问子对象中父对象的所有数据,那就太好了:php中的父对象,php,oop,class,Php,Oop,Class,是否有方法遍历对象以获取父对象数据? “父对象”不是指父类,而是字面上的对象。 这里有一个例子,在javascripty世界中:-): 如果我可以访问子对象中父对象的所有数据,那就太好了: class B{ //I know this doesn't exists, but it's what I wanted do do function B(){ $this->parent = $this->parent(); echo $this-&g
class B{
//I know this doesn't exists, but it's what I wanted do do
function B(){
$this->parent = $this->parent();
echo $this->parent->test; //it would ouput "hello world"
}
}
目前,我的解决方案是将父对象传递给子对象(作为引用)或使父对象成为全局对象。
你有更好的解决办法吗
谢谢 没有
您可以使用$this从超类访问变量:
<?php
class A {
public function __construct()
{
$this->foo = 'hello';
}
}
class B extends A {
public function printFoo()
{
echo $this->foo;
}
}
$b = new B();
$b->printFoo();
?>
将父对象传递给子对象是更好的解决方案。虽然这是一种不太受欢迎的共生关系 B()是否应该知道它是其属性的对象?很可能不会。这些只是通过组合松散地联系在一起
为什么B()必须是其父级的属性?您是否需要在B()中使用此实现,还是应该将其作为父级的一部分?我非常确定,PHP没有类似的功能
我认为,将父对象传递给子对象的解决方案是最好的解决方案。您应该考虑只将父属性设置在子的构造函数中,以防止多个父节点拥有相同的子。< P>不能调用
$parent->test = "hello world!";
$parent->child = new B();
并在B中自动引用$parent
一般来说,有四种方法可以构建类: 1。通过注入聚合父对象,例如
class B
{
private $parent;
public function __construct($parent)
{
$this->parent = $parent;
}
public function setParent($parent)
{
$this->parent = $parent;
}
public function accessParent()
{
$this->parent->someMethodInParent();
}
}
当对象在创建时必须有父对象时,使用构造函数注入。这是一种has-a关系,它产生了一种非常松散的耦合。B中没有硬编码的依赖项,因此您可以轻松地交换父实例,例如在单元测试时使用模拟。使用依赖项注入将使代码更易于维护
在您的用例中,在创建B时,您需要将$parent
传递给B:
$parent->child = new B($parent);
2。使用作文
class B
{
private $parent;
public function __construct()
{
$this->parent = new Parent;
}
public function accessParent()
{
$this->parent->someMethodInParent();
}
}
这也是一个has-a关系,但将父类耦合到B。它也不是一个现有的父实例,而是一个新实例。从措辞上看,我觉得由孩子创造父母有点奇怪。当依赖项是一个不被认为存在于根类之外的类,但它是它所表示的整个事物的一部分时,请使用此选项
对于您的用例,没有方法执行$parent->child=new B()除非$parent是一个单例,否则使用此方法时要知道父项是什么。如果是这样,您可以获得单例实例,例如Parent::getInstance()
,以实现您想要的功能,但是请注意,单例并不是每个人都喜欢的模式,例如难以测试
3。使用继承
class B extends Parent
{
public function accessParent()
{
$this->someMethodInParent();
}
}
通过这种方式,您可以创建is-a关系。父类(但不是特定实例)中的所有公共和受保护的方法和属性都将在B中可用,您可以通过B实例的$this
关键字访问它们
对于您的用例,这种方法不起作用,因为您根本不必有父实例,但B在创建父实例时会封装父实例的所有内容
$b = new B;
4。使用全局关键字
class B extends Parent
{
private $parent;
public function __construct()
{
global $parent;
$this->parent = $parent;
}
public function accessParent()
{
$this->parent->someMethodInParent();
}
}
global
关键字将全局变量导入当前范围。一般来说,在OO上下文中,但使用上述其他三种方法之一,最好是第一种。虽然它是一种语言特性,但人们并不赞成它——尽管它是第二个最接近第一个的特性,例如
$parent->child = new B();
无论如何,希望这能有所帮助。也许它在某些情况下会有用:它不会在构造函数中很早就将父对象带到子类,而是在一步之后。它可以拦截不存在的方法:
class ParentClass
{
const CHILD_PROPERTY_NAME = 'child';
public $data = 'Some data';
public function
__set($property_name, $property_value)
{
if ($property_name == self::CHILD_PROPERTY_NAME)
{
$property_value->set_parent_object($this);
}
}
}
class ChildClass
{
private $parent_object = null;
public function
set_parent_object($object)
{
$this->parent_object = $object;
echo $this->parent_object->data;
}
}
$p = new ParentClass();
$p->child = new ChildClass();
这将输出一些数据
您可以在创建子对象时创建对象子对象的集合。您通过父级创建它,这样他们就不能相互引用,但您可以通过父级和子级访问父级和子级
class ChildObject
{
public $name;
}
class ParentObject
{
public $children = array();
public function new_child($text = 'my name is data')
{
$child = new ChildObject; // create a new child
$child->name = $text; // assign the name
$this->children[] = $child; // store it as part of this object
return $child; // return the new instance of Child
}
public function print_everything ()
{
foreach($this->children as $child) {
echo $child->name;
}
}
}
$parent = new ParentObject;
$child1 = $parent->new_child(); // this is a ChildObject not a ParentObject
$child2 = $parent->new_child('i am not data');
echo $child1->name; // 'my name is data'
echo $child2->name; // 'i am not data'
$child1->name = 'something else';
echo $child1->name; // 'something else'
$parent->print_everything(); // 'something else' and 'i am not data'
因此,如果要访问父方法或属性,应将其放在父方法或属性中,而不是子方法或属性中。请记住,父对象也是其自己类的“实例”。它只是两个相互引用的对象。你可以称他们为父母和孩子。为什么你需要孩子引用他的父母?家长中是否也有孩子需要访问的内容?如果是这样的话,你最好将它可能需要的任何东西传递给孩子,而不是试图从家长那里获取。我在家长中有一个“隐私对象”,那么我在孩子中需要的一些变量,传递它们都会很乏味…$child=new B($parent->privacy);行吗?B()的实例是否需要是$parent的类属性?是的,但这还不够:我需要$child=new B($parent->user,$parent->privacy,$parent->url);然后为了方便起见,我切换到$child=newb($parent);这不是问题所在。他不想访问超类。我认为这个答案很好(“否”)。Sjoerd还提供了另一种解决方案。在javascript使用了一个月后,遍历对象是正常的,在这种情况下,我发现php太“静态”了。考虑一个mvc框架,其中一些属性是在途中定义的,而不是在默认情况下定义的,最后主控制器类调用一个触发子对象创建的方法。如果我使用Sjoerd的“extends”方法,那么我就不能访问在途中创建的属性,只能访问在类顶部定义的属性。所以你需要传递一个包含你正在构建的信息的对象?也许你应该重新考虑这个设计来减少耦合-依赖注入容器在这里会有帮助吗?这太奇怪了,谢谢你让这篇文章保持最新,Gordon。美好的
class ChildObject
{
public $name;
}
class ParentObject
{
public $children = array();
public function new_child($text = 'my name is data')
{
$child = new ChildObject; // create a new child
$child->name = $text; // assign the name
$this->children[] = $child; // store it as part of this object
return $child; // return the new instance of Child
}
public function print_everything ()
{
foreach($this->children as $child) {
echo $child->name;
}
}
}
$parent = new ParentObject;
$child1 = $parent->new_child(); // this is a ChildObject not a ParentObject
$child2 = $parent->new_child('i am not data');
echo $child1->name; // 'my name is data'
echo $child2->name; // 'i am not data'
$child1->name = 'something else';
echo $child1->name; // 'something else'
$parent->print_everything(); // 'something else' and 'i am not data'