Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
php中的父对象_Php_Oop_Class - Fatal编程技术网

php中的父对象

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

是否有方法遍历对象以获取父对象数据? “父对象”不是指父类,而是字面上的对象。 这里有一个例子,在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->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::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'