【发布时间】:2019-08-15 19:08:53
【问题描述】:
我正在尝试创建一个类 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
当我在create 方法中删除: self 类型提示时它可以工作,但我不明白为什么它们不兼容,如果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);
}
}
【问题讨论】:
-
Person::create():self的返回类型(即返回类型 Person)!==Developer::create():self(返回类型开发人员)。Developer::create() : Person { class code here }应该可以正常工作。 -
@jibsteroos 是的,这会起作用,但是开发者的 create 方法旨在返回 Developer 的一个实例,覆盖 Person 的 create 方法。一种简单的方法是创建具有不同名称的方法,例如(createPerson、createDeveloper),但我认为我误解了这种模式的某些内容,必须有正确的方法来解决这个问题。
-
$dev = Developer::create('alex', 'pearson', 3, 'c++');然后var_dump($dev)显示它是object(Developer)#2 (4) {...} -
@jibsteroos 你是对的!我认为 PHP 应该认识到
Developer扩展了Person,并允许它作为 create 方法的返回提示。相反,当方法返回提示为Person时,它返回一个Developer实例,这对我来说毫无意义。感谢您的帮助! -
确实,很奇怪,不知道应该是这个样子,可能是bug……
标签: php inheritance type-hinting static-factory named-constructor