PHP 中的抽象类如何返回扩展它的子类的类型?
abstract class MyAbstractClass {
public static function fromID($id) : returnType { <======
...
}
}
class MyChildClass extends MyAbstractClass {
public function specificFunctionToThisClass(){
...
}
}
$item = new MyChildClass()->fromID(3);
$item->specificFunctionToThisClass();
上面的例子过于简单了。
现在,如果我在任何子类中调用方法 fromID(var),它们将返回类型为 MyAbstractClass 的对象。我如何在 MyAbstractClass 中定义该函数的返回类型,以便无论哪个孩子调用该方法,它都会返回孩子的类而不是父类。
仅供参考,我知道我可以在每个子级中实现相同的函数,并将调用重定向到父级,但指定更具体的返回类型。长话短说,我的子类超过 100 个,仅在父类上定义它会容易得多,这样将来就不需要在每个子类上对代码进行任何更改
returnType
应该是 MyAbstractClass
,没有任何实现(子实现)。
这可能是不可能的,但子级可以返回它自己的实例。对于动态配置,
$model
可以具有特定于父级和子级的配置。
使用
abstract class
和 abstract static function
让一切变得抽象:
abstract class Model {
abstract static function fromArray( array $model ): Model;
abstract static function fromID( int $id ): Model;
}
class LightSettings extends Model {
public function __construct( array|null $config ) {
parent::__construct( $config );
}
static function fromArray( array $model ): LightSettings {
return new LightSettings( $model );
}
static function fromID( int $$preset_id ): LightSettings {
return new LightSettings( null )->load( $preset_id );
}
...
}
构造函数显然也可以采用
int $$preset_id
,但它很灵活。
本想这是一条评论,但评论太长了。
基于 Martin Zeitler 的答案(对不起,Martin,我在下面复制您的代码),在 Model 类中使用额外的静态方法:
abstract class Model {
abstract static function fromArray( array $model ): Model;
abstract static function fromID( int $id ): Model;
// Common stuff for the fromArray factory
protected static function populateFromArray(Model $model, array $modelArray): Model {
// Do whatever is common here
return $model;
}
class LightSettings extends Model {
static function fromArray( array $model ): LightSettings {
return parent::populateFromArray(new LightSettings(), $model);
}
enter code here
static function fromID( int $$preset_id ): LightSettings {
// Similar implementation as in fromArray()
}
...
}
好的,你的问题是:
PHP 中的抽象类如何返回扩展它的子类的类型?
分别
我如何在中定义该函数的返回类型 MyAbstractClass 这样无论哪个孩子调用该方法都会 返回孩子的班级而不是父班级。
简短的回答是:你不能
继承是自上而下进行的...在任何情况下父类都不能知道它是子类。
想象一个框架。框架中的类旨在派生。但继承的类不是框架的作者编写的,而是一些下载了该框架并在他/她的项目中使用它的开发人员编写的。可能有成千上万的开发人员做了同样的事情,但使用了不同的子类。框架的作者如何知道所有的派生类?他不能,对吧?
我想这可以通过使用
static
关键字来实现。不像静态变量 bu 中的 self
的替代品那样,意味着调用此方法的实例的类。出于某种原因,PHP 认为给两个不同的事物赋予相同的名称不是问题。
无论如何,定义的返回类型不会影响返回值。它只是检查返回值是否与我们想要的类型匹配。
所以答案是创建与子对象具有相同类的对象:
abstract class MyAbstractClass {
public static function fromID($id) : MyAbstractClass { // This is on purpose. The child class is considered an instance of the parent class so it's fine
return new static();
}
}
class MyChildClass extends MyAbstractClass {
public function specificFunctionToThisClass(){
echo get_class($this);
}
}
$item = (new MyChildClass())->fromID(3);
$item->specificFunctionToThisClass(); // prints 'MyChildClass'
如果您的子类方法不是静态的,您将需要:
abstract class ModelAbstract {
abstract function fromArray( array $array): object;
}
class ChildClass extends ModelAbstract {
function fromArray( array $array ): ChildClass {
//your code ...
return $this;
}
}
如果你的子类的方法是静态的,那么:
abstract class ModelAbstract {
abstract static function fromArray( array $array): static;
}
class ChildClass extends ModelAbstract {
static function fromArray( array $array ): ChildClass {
//your code ...
return new static();
}
}