Статический фабричный шаблон с наследованием и подсказками типов - PullRequest
0 голосов
/ 25 марта 2019

Я пытаюсь создать класс Developer, который является подклассом Person.
Я хочу, чтобы они оба использовали статический шаблон фабрики (или «именованные конструкторы»).

Я видел несколько примеров этого паттерна, но ни один из них не использует наследование.

Вопрос 1
В примерах они делают метод конструктора всегда закрытым.
Можно ли сделать его защищенным для вызова из дочернего конструктора?
Или я должен решить проблему, делая конструкторы всегда закрытыми и пытаясь построить наследование, вызывая метод create родителя из метода create дочернего элемента?

Вопрос 2
Когда я пытаюсь создать экземпляр класса Person или Developer, я получаю сообщение об ошибке ниже. Почему?

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

Это работает, когда я удаляю подсказки типа : self в обоих методах create, но я не понимаю, почему они несовместимы, если Developer является дочерним классом Person.

Заранее спасибо.

<?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);
    }
}

1 Ответ

0 голосов
/ 25 марта 2019

Вопрос 1:

В примерах метод конструктора всегда закрыт. Можно ли сделать его защищенным для вызова из дочернего конструктора?

Вы должны сделать это защищенным. В противном случае child не сможет вызвать метод родителя.

Вопрос 2:

Это работает, когда я удаляю подсказки типа: self в обоих методах create, но я не понимаю, почему они несовместимы, если Developer является дочерним классом Person.

Попробуйте использовать static вместо self. Это может сработать, но я не уверен. Но вы все равно получите уведомление (или предупреждение, не помните), потому что заводской метод в Developer имеет параметры, отличные от Person. В PHP это разрешено, но не рекомендуется.

...