【问题标题】:Instantiating one instance each of parent's class children?为每个父母的班级孩子实例化一个实例?
【发布时间】:2017-08-02 02:46:23
【问题描述】:

为了测试我的东西,我想为我命名的父类的每个子类自动实例化一个实例,而无需手动调用类名(太多了)。

例如:

Class Animal {
  public weight;
}

Class Dog extends Animal {
  public weight = 20;
}

Class SmallDog extends Dog {
  public weight = 18;
}

Class Cat extends Animal {
  public weight = 10;
}


function xy(){
  $classes = array();
  foreach parent->child as child(){
    $classes[] = new child()
  }
  //$classes = [Dog, SmallDog, Cat]
}

像 (tm) 这样的东西是否可行,如果可行,如何实现?

作为进一步的信息,我有一个包含每个类的 autoload_register,但它也包含我不想实例化的各种类。 另外,相对于上面的例子,我将 Animal、Dog 和 Cat 都组装在一个文件中,我们称之为 animal.php。

在上面的代码中,我会得到一个低于 Animal 的任何实例,包括 SmallDog。如果不可能,我可以得到 Dog 和 Cat 并调用父为 Dog 的函数(以实例化 SmallDog)。

感谢您的建议,

【问题讨论】:

  • 您可以使用get_declared_classes()ReflectionClass::getParentClass() 来查找扩展某个类的类(假设所有包含子类的文件都已加载)但这会使您的代码更难阅读和理解.只列出子类要清楚得多。您可以使用一些简单的 shell 脚本(grepsed/cut 等)从代码中提取子类列表。
  • 这违背了测试的想法。您可以继承和覆盖函数,因为每个子类的行为与其父类不同。您必须对它们进行测试。

标签: php class inheritance


【解决方案1】:

这在实际情况下并不是很有用,但使用@axiac 注释可以实现ChildrenResolver 类:

class ChildrenResolver
{ 
    protected $defaultClasses = [
        0 => 'stdClass',
        1 => 'Exception',
        2 => 'ErrorException',
        // ...
    ];

    protected $declaredClasses;

    public function __construct(array $declaredClasses = null)
    {
        if (is_null($declaredClasses)) {
            $declaredClasses = array_diff(
                get_declared_classes(),
                $this->defaultClasses
            );
        }

        $this->declaredClasses = $declaredClasses;
    }

    public function getChildClasses($class)
    {
        return array_filter(
            $this->declaredClasses,
            function ($declaredClassName) use ($class) {
                $declaredClass = new ReflectionClass($declaredClassName);

                while(($parent = $declaredClass->getParentClass())) {
                    if ($parent->name === $class) {
                        return true;
                    }

                    $declaredClass = $parent;
                }

                return false;
            }
        );
    }

    public function getDirectChildClasses($class)
    {
        return array_filter(
            $this->declaredClasses,
            function ($declaredClassName) use ($class) {
                $declaredClass = new ReflectionClass($declaredClassName);

                $parent = $declaredClass->getParentClass();

                return $parent ? $parent->name === $class : false;
            }
        );
    }
}

这个想法很简单。我们循环声明的类(通过get_declared_classes 获得),使用ReflectionClass 反映每个类,并将我们从ReflectionClass::getParentClass 获得的父类与给定的父类进行比较。为了方便起见,我使用了array_filter 函数。

有了这个类,你可以像这样解决孩子:

$childrenResolver = new ChildrenResolver;

var_dump($childrenResolver->getChildClasses('Animal'));
var_dump($childrenResolver->getDirectChildClasses('Animal'));
var_dump($childrenResolver->getChildClasses('Dog'));

这里是working demo

【讨论】:

    猜你喜欢
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 2013-06-23
    • 2015-08-10
    • 2014-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多