简体   繁体   English

具有继承和类型提示的静态工厂模式

[英]Static factory pattern with inheritance and type hints

I'm trying to make a class Developer which is a subclass of Person . 我试图做一个类Developer是的子类Person
I want both of them to use the static factory pattern (or "named constructors"). 我希望他们俩都使用静态工厂模式(或“命名构造函数”)。

I've seen some examples of that pattern, but none of them using inheritance. 我已经看到了这种模式的一些例子,但没有一个使用继承。

Question 1 问题1
In the examples they make the constructor method always private. 在示例中,它们使构造方法始终保持私有。
Is it ok to make it protected in order to be called from the child constructor? 为了从子构造函数调用它是否可以保护它?
Or should I address the problem making the constructors always private, and trying to build the inheritance calling the parent's create method from the child's create method? 或者我应该解决使构造函数始终保持私有的问题,并尝试构建从子的create方法调用父的create方法的继承?

Question 2 问题2
When I try to instantiate either class Person or Developer, I'm getting the error below. 当我尝试实例化类Person或Developer时,我收到以下错误。 Why? 为什么?

PHP Fatal error:  Declaration of Developer::create(string $name, string $surname, ?int $yearsOfExperience = NULL, ?string $preferredLanguage = NULL): Developer must be compatible with Person::create(string $name, string $surname): Person in InheritanceTest.php on line 57

It works when I delete the : self type hints in both create methods, but I don't understand why are they incompatibles, if Developer is a child class of Person . 它在我在两个create方法中删除: self类型提示时都有效,但我不明白它们为什么不兼容,如果DeveloperPerson的子类。

Thanks in advance. 提前致谢。

<?php

class Person
{
    protected $name;
    protected $surname;

    protected function __construct(string $name, string $surname)
    {
        $this->name = $name;
        $this->surname = $surname;
    }

    public static function create(string $name, string $surname): self
    {
        // Some validation

        if($name == ''){
            throw new InvalidArgumentException('A person name can not be empty.');
        }

        if($surname == ''){
            throw new InvalidArgumentException('A person surname can not be empty.');
        }

        return new self($name, $surname);
    }
}

class Developer extends Person
{
    protected $yearsOfExperience;
    protected $preferredLanguage;

    protected function __construct(string $name, string $surname, ?int $yearsOfExperience, ?string $preferredLanguage)
    {
        parent::__construct($name, $surname);

        $this->yearsOfExperience = $yearsOfExperience;
        $this->preferredLanguage = $preferredLanguage;
    }

    public static function create(string $name, string $surname, ?int $yearsOfExperience = null, ?string $preferredLanguage = null): self
    {
        // Some validation

        if($yearsOfExperience < 0){
            throw new InvalidArgumentException('The years of experience can not be negative.');
        }

        if($preferredLanguage == ''){
            throw new InvalidArgumentException('The preferred language can not be empty.');
        }

        return new self($name, $surname, $yearsOfExperience, $preferredLanguage);
    }
}

Question 1: 问题1:

In the examples they make the constructor method always private. 在示例中,它们使构造方法始终保持私有。 Is it ok to make it protected in order to be called from the child constructor? 为了从子构造函数调用它是否可以保护它?

You have to make it protected. 你必须保护它。 Otherwise child will not be allowed to call the parent's method. 否则将不允许孩子调用父母的方法。

Question 2: 问题2:

It works when I delete the : self type hints in both create methods, but I don't understand why are they incompatibles, if Developer is a child class of Person. 它在我在两个create方法中删除:self类型提示时都有效,但我不明白它们为什么不兼容,如果Developer是Person的子类。

Try using static instead of self . 尝试使用static而不是self It might work, but I am not sure. 它可能会奏效,但我不确定。 But you will still have notice (or warning, don't remember) because factory method in Developer has different parameters than Person. 但是你仍然会注意到(或警告,不记得),因为Developer中的工厂方法具有与Person不同的参数。 In PHP this is allowed but not recommended. 在PHP中,这是允许的,但不推荐。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM