我已經設定了一個抽象類,它必須執行另一個實體化類的方法。所以我設定了一個匿名類來擴展我的抽象類,并且在實作的方法中,我想訪問那個“其他實體化類”的方法,但是為了讓我的 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 的型別必須是物件(如在類 blah 中)
我可以將屬性“參考”復制到另一個變數并將型別提示設定為“世界”,但這不是最好的
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();
}
};
uj5u.com熱心網友回復:
值得理解為什么PHP 會告訴您不能更改屬性型別。
由于這是一個protected屬性,它可以由父類或子類讀取和寫入。例如,父類可能有這樣的方法,這些方法將被子類繼承:
public function getReference(): object {
return $this->reference;
}
public function setReference(object $newReference): void {
$this->reference = $newReference;
}
public function setReferenceToDefault(): void {
$this->reference = new SomethingBoring;
}
如果您在子類中指定world為的型別,該方法將正常作業 - 的任何實體都是物件,因此回傳型別是可以的。但是and方法會失敗,因為它們試圖分配不是 type 的東西。$referencegetReferenceworldsetReference()setReferenceToDefault()world
本質上,通過在基類上宣告一個受保護的屬性,您為所有子類設定了一個契約,PHP 正在為您強制執行它。對此的技術術語是“逆變”:子類可以更慷慨地接受它,但它不能拒絕父類會接受的值。相反的是“協方差”,它適用于回傳值:子類可以更具體地說明它將回傳什么,但不能回傳父類永遠不會回傳的東西。當某些東西既是輸入又是輸出時,您會受到兩種限制,因此根本無法改變型別。
由于您實際上并未在基類上使用該屬性,因此實際上不需要此限制,因此在這種情況下,一種選擇就是不要在基類上定義屬性或建構式。在其他情況下,您可能希望使用“編譯器輔助復制和粘貼”的
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/466878.html
