PHP 键入从对象到我的 class 的提示,这不可能吗?
PHP type hinting from object to my class, not possible?
我设置了一个抽象 class,它必须从另一个实例化 class 执行方法。
所以我设置了一个匿名 class 来扩展我的抽象 class 并且在实现的方法中,我想访问那个“其他实例化 class” 的方法,但是对于我的 IDE 为了帮助我找到方法和参数的正确名称,我必须在某处写下类型。
abstract class blah
{
protected object $reference;
public function __construct(object $reference)
{
$this->reference = $reference;
$this->hello();
}
abstract public function hello();
}
class world
{
public function __construct()
{
new class($this) extends blah {
public function hello()
{
$this->reference->display();
}
};
}
public function display()
{
echo 'hello world';
}
}
new world();
我无法将类型从“对象”更改为其他类型以允许我的 IDE 显示方法
public function __construct()
{
new class($this) extends blah {
protected world $reference;
public function hello()
{
$this->reference->display();
}
};
}
这抛出
致命错误:blah@anonymous::$reference 的类型必须是对象(如 class blah)
我可以将属性“reference”复制到另一个变量并将类型提示设置为“world”,但这不是最好的
public function __construct()
{
new class($this) extends blah {
protected world $reference;
public function hello()
{
/** @var world $hello */
$hello = $this->reference;
$hello->display();
}
};
}
我有什么更好的解决方案?
编辑:这似乎可行,这是最好的方法吗?
new class($this) extends blah {
/** @var world $reference */
protected object $reference;
public function hello()
{
$this->reference->display();
}
};
如果您只想 IDE 使用它,则使用文档块覆盖类型声明(如果 IDE 支持):
/**
* @property world $reference
*/
new class($this) extends blah {
public function hello()
{
$this->reference->display();
}
};
例如PHPStorm 虽然不支持匿名 class,但支持普通 class 描述:
值得理解 为什么 PHP 告诉你不能更改 属性 类型。
由于这是 protected
属性,它可以被 parent 或 child 读取 并写入 class。例如,parent class 可能有这样的方法,这些方法将被 child class:
继承
public function getReference(): object {
return $this->reference;
}
public function setReference(object $newReference): void {
$this->reference = $newReference;
}
public function setReferenceToDefault(): void {
$this->reference = new SomethingBoring;
}
如果您在 child class 中将 world
指定为 $reference
的类型,则 getReference
方法将正常工作 - [ 的任何实例=12=] 是一个 object,所以 return 类型是可以的。但是 setReference()
和 setReferenceToDefault()
方法会失败,因为它们试图分配一些不属于 world
.
类型的东西
本质上,通过在基础 class 上声明一个受保护的 属性,您正在为所有 child [=55] 设置一个 contract =]es,PHP 正在为您强制执行。这方面的技术术语是“逆变”:child class 可以 更慷慨 它接受的内容,但它不能拒绝值 parent 会接受。相反的是“协方差”,它适用于 returning 值:child class 可以 更具体 会 return,但不能 return parent class 永远不会。当某物既是输入又是输出时,您会同时受到限制,因此根本无法改变类型。
由于您实际上并没有在基础 class 上使用 属性,因此实际上不需要此限制,因此在这种情况下,一个选择就是 不在基础 class 上定义 属性 或构造函数。在其他情况下,您可能想要使用 traits,它们是“编译器辅助的 copy-and-paste”:它们不会断言两个 [=55= 之间的任何 关系 ] 是的,但它们可以避免您多次编写相同的代码。
我设置了一个抽象 class,它必须从另一个实例化 class 执行方法。 所以我设置了一个匿名 class 来扩展我的抽象 class 并且在实现的方法中,我想访问那个“其他实例化 class” 的方法,但是对于我的 IDE 为了帮助我找到方法和参数的正确名称,我必须在某处写下类型。
abstract class blah
{
protected object $reference;
public function __construct(object $reference)
{
$this->reference = $reference;
$this->hello();
}
abstract public function hello();
}
class world
{
public function __construct()
{
new class($this) extends blah {
public function hello()
{
$this->reference->display();
}
};
}
public function display()
{
echo 'hello world';
}
}
new world();
我无法将类型从“对象”更改为其他类型以允许我的 IDE 显示方法
public function __construct()
{
new class($this) extends blah {
protected world $reference;
public function hello()
{
$this->reference->display();
}
};
}
这抛出 致命错误:blah@anonymous::$reference 的类型必须是对象(如 class blah)
我可以将属性“reference”复制到另一个变量并将类型提示设置为“world”,但这不是最好的
public function __construct()
{
new class($this) extends blah {
protected world $reference;
public function hello()
{
/** @var world $hello */
$hello = $this->reference;
$hello->display();
}
};
}
我有什么更好的解决方案?
编辑:这似乎可行,这是最好的方法吗?
new class($this) extends blah {
/** @var world $reference */
protected object $reference;
public function hello()
{
$this->reference->display();
}
};
如果您只想 IDE 使用它,则使用文档块覆盖类型声明(如果 IDE 支持):
/**
* @property world $reference
*/
new class($this) extends blah {
public function hello()
{
$this->reference->display();
}
};
例如PHPStorm 虽然不支持匿名 class,但支持普通 class 描述:
值得理解 为什么 PHP 告诉你不能更改 属性 类型。
由于这是 protected
属性,它可以被 parent 或 child 读取 并写入 class。例如,parent class 可能有这样的方法,这些方法将被 child class:
public function getReference(): object {
return $this->reference;
}
public function setReference(object $newReference): void {
$this->reference = $newReference;
}
public function setReferenceToDefault(): void {
$this->reference = new SomethingBoring;
}
如果您在 child class 中将 world
指定为 $reference
的类型,则 getReference
方法将正常工作 - [ 的任何实例=12=] 是一个 object,所以 return 类型是可以的。但是 setReference()
和 setReferenceToDefault()
方法会失败,因为它们试图分配一些不属于 world
.
本质上,通过在基础 class 上声明一个受保护的 属性,您正在为所有 child [=55] 设置一个 contract =]es,PHP 正在为您强制执行。这方面的技术术语是“逆变”:child class 可以 更慷慨 它接受的内容,但它不能拒绝值 parent 会接受。相反的是“协方差”,它适用于 returning 值:child class 可以 更具体 会 return,但不能 return parent class 永远不会。当某物既是输入又是输出时,您会同时受到限制,因此根本无法改变类型。
由于您实际上并没有在基础 class 上使用 属性,因此实际上不需要此限制,因此在这种情况下,一个选择就是 不在基础 class 上定义 属性 或构造函数。在其他情况下,您可能想要使用 traits,它们是“编译器辅助的 copy-and-paste”:它们不会断言两个 [=55= 之间的任何 关系 ] 是的,但它们可以避免您多次编写相同的代码。