首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在PHP中将父类转换为它的子类?

如何在PHP中将父类转换为它的子类?
EN

Stack Overflow用户
提问于 2018-06-27 03:33:21
回答 3查看 2.7K关注 0票数 -2

在PHP中可以将父类转换为它的子类吗?如果没有,什么是实现这一目标的最有效的替代方案?

例如,以下结果会导致错误:

代码语言:javascript
复制
<?php
class Foo {
    public $test;
    public static function create(): self {
        $a = new self();
        $a->test = 123;
        return $a;
    }
}

class Bar extends Foo {
    public $baz;
    public static function create(): self {
        $b = (self) parent::create(); // <--- Is this possible?
        $b->baz = 456;
        return $b;
    }
}

$bar = Bar::create();

var_dump($bar); /* should output:
  object(Bar)[35]
    public 'baz' => int 456
    public 'test' => int 123 */
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-08-10 04:17:07

我能够使用以下策略来实现这一点:

代码语言:javascript
复制
class Foo {
    public $test;
    public static function create(array $row): self {
        $a = new static();
        $a->test = $row['Test'];
        return $a;
    }
}

class Bar extends Foo {
    public $baz;
    public static function create(array $row): Foo {
        $b = parent::create($row);
        $b->baz = $row['Baz'];
        return $b;
    }
}

$test = Bar::create([
    'Test' => 123,
    'Baz' => 456,
]);

var_dump($test);
/* Outputs:
    object(Bar)#2 (2) {
        ["baz"]=> int(456)
        ["test"]=> int(123)
    } */
票数 0
EN

Stack Overflow用户

发布于 2018-06-27 05:57:19

当您声明Bar扩展Foo时,默认的Foo构造函数调用Bar构造函数以初始化其父属性(在本例中为public $test)。如果为子类定义自定义构造函数,则还应调用父构造函数。This section of the PHP documentation describes how this works

代码语言:javascript
复制
<?php
class BaseClass {
    function __construct() {
        print "In BaseClass constructor\n";
    }
}

class SubClass extends BaseClass {
    function __construct() {
        parent::__construct();
        print "In SubClass constructor\n";
    }
}

class OtherSubClass extends BaseClass {
    // inherits BaseClass's constructor
}

// In BaseClass constructor
$obj = new BaseClass();

// In BaseClass constructor
// In SubClass constructor
$obj = new SubClass();

// In BaseClass constructor
$obj = new OtherSubClass();

对于示例中的特定功能,我倾向于将代码的逻辑放入受保护的构造函数中,并从工厂方法中调用它们:

代码语言:javascript
复制
<?php
class Foo {
    public $test;

    protected function __construct() {
        $this->test = 123;
    }

    public static function create(): Foo {
        return new self();
    }
}

class Bar extends Foo {
    public $baz;

    protected function __construct() {
        parent::__construct();
        $this->baz = 456;
    }

    public static function create(): Foo {
        return new self();
    }
}

请注意,我已经将函数create()的返回类型更改为始终为Foo。PHP不允许您更改从父类覆盖的函数的返回类型,在两个实例中使用self都可以做到这一点。

然而,这不是问题。正如您所期望的,Bar::create()为我们提供了一个Bar对象。返回类型只需要与Foo兼容,而且因为Bar实现了Foo的接口,所以它被认为是类型兼容的。

您可以使用static关键字进一步简化此代码:

代码语言:javascript
复制
<?php
class Foo {
    public $test;

    protected function __construct() {
        $this->test = 123;
    }

    public static function create(): Foo {
        return new static();
    }
}

class Bar extends Foo {
    public $baz;

    protected function __construct() {
        parent::__construct();
        $this->baz = 456;
    }
}

var_dump(Bar::create()); /* Outputs:
    object(Bar)#1 (2) {
    ["baz"]=>
    int(456)
    ["test"]=>
    int(123)
    }
*/

使用受保护的构造函数可能不是一种选择,例如,因为你已经有了一个带有必需参数的公共构造函数或类似的情况。在这种情况下,您必须采用其他答案中解释的方法,即创建临时Foo并将属性值复制到新的Bar对象中:

代码语言:javascript
复制
<?php
class Foo {
    public $test;

    public static function create(): Foo {
        $result = new self();
        $result->test = 123;
        return $result;
    }
}

class Bar extends Foo {
    public $baz;

    public static function create(): Foo {
        $foo = parent::create();
        $result = new self();
        foreach($foo as $property => $value) {
            $result->$property = $value;
        }
        $result->baz = 456;
        return $result;
    }
}

var_dump(Bar::create()); /* Outputs:
    object(Bar)#2 (2) {
    ["baz"]=>
    int(456)
    ["test"]=>
    int(123)
    }
*/
票数 1
EN

Stack Overflow用户

发布于 2018-06-27 03:51:54

我不认为有任何内置的东西可以做到这一点。您可以在子类中编写一个函数,该函数接受父类的一个实例并返回一个具有相同内容的子类。

代码语言:javascript
复制
class Bar extends Foo {
    public static function FooFromBar($foo) {
        $bar = new Bar();
        $bar->prop1 = $foo->prop1;
        $bar->prop2 = $foo->prop2;
        // continue for all properties
        return $bar;
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51050212

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档