Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/254.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

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_Factory - Fatal编程技术网

Php 如何在_构造中使用其父工厂实例化子类

Php 如何在_构造中使用其父工厂实例化子类,php,oop,factory,Php,Oop,Factory,我有一个类a,它必须使用其他multiples对象实例化 class A{ function __construct(new X(), new Y(), new Z()){ $this->foo = 'foo'; } } 为了省去这个类实例化的麻烦,我为这个类设置了一个工厂 class A_Factory{ public static function create_A(){ return new A(new X(), new Y(), n

我有一个类a,它必须使用其他multiples对象实例化

class A{
   function __construct(new X(), new Y(), new Z()){
      $this->foo = 'foo';
   }
}
为了省去这个类实例化的麻烦,我为这个类设置了一个工厂

class A_Factory{
    public static function create_A(){
        return new A(new X(), new Y(), new Z());
    }
}
我有一个扩展了类a的类B。我的问题是我不知道如何在B类中实例化a类以访问属性“foo”

我觉得很自然地尝试:

class B extends A{
   function __construct(){
      A_Factory::create_A();  
   }
}
但在尝试访问对象a属性时会生成一个通知错误:

Undefined property: A::$foo

如何使用类A工厂在其子类中轻松实例化?谢谢。

您对继承的工作原理有一点误解。我认为因为B的构造器中的那一行:

A_Factory::create_A();
父类不是子类的属性。如果在B的构造函数中创建一个
新的a([…])
,它将是另一个类,与B完全分离,并且无法将其“合并”到现有对象。要从子类构造父类,可以执行以下操作:

class B {
    function __construct() {
        parent:__construct(new X(),new Y(),new Z());
    }
}
下面是一种使用工厂和一些类型提示创建类的方法。请注意,我是如何移动不同的
new XYZ()
,使它们不在类构造函数中的。构造函数中的裸体新闻在某种程度上被认为是不好的做法,因为它隐藏了类的依赖关系

class B_Factory {
    public static function create_B(X $X,Y $Y, Z $Z) {
        return new B($X, $Y, $Z);
    }
}

class X {}
class Y {}
class Z {}

class A {
    public function __construct(X $X, Y $Y, Z $Z) {
        $this->foo = "foo";
    }
}

class B extends A {
    public function __construct(X $X, Y $Y, Z $Z) {
        parent::__construct($X,$Y,$Z);
    }
}

$B = B_Factory::create_B(new X(), new Y(), new Z());
var_dump($B->foo);
真正的答案:您希望您的工厂是一个依赖项注入容器,例如,通过使用类型提示,您的类将使用它们的依赖项递归创建

在您的案例中(改编自auryn的github repo中的一个示例):


使用反射,Auryn可以递归地理解类需要的组件,实例化它们并将它们传递给类构造函数。

您尝试使用
A_工厂::create_A()
,方法与使用
父::_construct()
相同。然而,这是两个完全不同的调用

父项::_构造()
parent
解析为
A
。当前对象
$this
A
的实例(因为继承导致
B
的每个实例也是
A
的实例)。在这种情况下,呼叫是而不是静态呼叫,尽管已经使用了操作员
$this
保持不变)

以下代码起作用: (假定
foo
不是
private

这一个也有效: 工厂
A\u工厂::createA()
是一个静态调用,因为
A\u工厂
不在
B
的继承树中。另外,
A_工厂
创建返回A的新实例。因此,一旦调用它,您就有两个不同的对象:
$this
仍然是未更改的
B
实例,并且您创建了
a
的不同实例,而没有将其分配给任何变量

一种可能的方法是将工厂方法移动到
A
本身

这将有助于: 这利用了with
static
关键字
static
解析为被调用类的类名,因此它在
A::create()
中是
A
,在
B::create()
中是
B


请注意与
self
的区别,它总是解析为声明方法的类(在这种情况下,它总是
A

父项::\u构造?工厂的重点不是在a的实例化中使用construct和所需对象的列表,你确定这是一个好的设计吗?我不明白为什么要创建实例,如果类是继承的如果类是继承的如果类是继承的,所以只要使用
$this->foo
。除非
foo
仅在
A
的构造函数中设置,您在
B
中重载该构造函数,否则在这种情况下,您需要首先调用
parent::\uu construct()
。如果I
A
有多个子项,例如
B
C
D
E
等,则声明
父项:\uu construct(新X、新Y、新Z)如果将来
A
的构造发生变化,那么每个子类中的
都将很难维护代码。在这种情况下,您会建议使用您提到的工厂方法吗?是的,我建议使用。除非对象创建变得更复杂和多样化,否则将实例化与类本身分离会带来更大的收益使用类似于或的模式获得
class X {}
class Y {}
class Z {}

class A {
    public function __construct(X $X, Y $Y, Z $Z) {
        $this->foo = "foo";
    }
}

class B extends A {
    public function __construct(X $X, Y $Y, Z $Z) {
        parent::__construct($X, $Y, $Z);
    }
}

$injector = new Auryn\Injector;
$B = $injector->make('B');
var_dump($B->foo);
class B extends A
{
    function __construct()
    {
        parent::__construct(new X, new Y, new Z);
        echo $this->foo;
    }
}
class B extends A
{
    function __construct()
    {
        A::__construct(new X, new Y, new Z);
        echo $this->foo;
    }
}
class A
{
    function __construct(X $x, Y $y, Z $z)
    {
        $this->foo = 'foo';
    }
    public static function create()
    {
        return new static (new X, new Y, new Z);
    }
}

class B extends A
{
}

// Instantiating:
$a = A::create();
$b = B::create();