首页 > 解决方案 > 具有继承和类型提示的静态工厂模式

问题描述

我正在尝试创建一个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,但我不明白为什么它们不兼容,如果DeveloperPerson.

提前致谢。

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

标签: phpinheritancetype-hintingstatic-factorynamed-constructor

解决方案


问题一:

在示例中,它们使构造函数方法始终为私有。是否可以对其进行保护以便从子构造函数中调用?

你必须保护它。否则不允许孩子调用父母的方法。

问题2:

当我在两个创建方法中删除 : self 类型提示时它会起作用,但我不明白为什么它们不兼容,如果 Developer 是 Person 的子类。

尝试使用static而不是self. 它可能有效,但我不确定。但是您仍然会注意到(或警告,不记得了),因为 Developer 中的工厂方法具有与 Person 不同的参数。在 PHP 中这是允许的,但不建议这样做。


推荐阅读