亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

聲明與接口不兼容 (PHP)

聲明與接口不兼容 (PHP)

PHP
九州編程 2023-09-08 16:37:43
假設我有一個父類和兩個這樣的子類abstract class Vehicle {    public function setManufacturer(string $manufacturer) { ... }}class Bicycle extends Vehicle {    public function addSaddle() { ... }}class Car extends Vehicle {    public function setSpeedLimit(float $limit) { ... }}現在我想通過這樣的接口使用這些對象interface VehicleInterface {    public function create(Vehicle $vehicle);}class BicycleService implements VehicleInterface {    public function create(Bicycle $bicycle) {        $bicycle->setManufacturer('Some company'); // Common for all Vehicle objects        $bicycle->addSaddle(); // Common only for Bicycle objects    }}看來這是不可能的,因為BicycleService create(...)與接口不兼容。除了刪除類型提示之外,還有什么辦法可以解決這個問題嗎?
查看完整描述

4 回答

?
紫衣仙女

TA貢獻1839條經驗 獲得超15個贊

當你在班級中實施時,你必須遵守合同。因此,無論對實現進行分類,該類都Vehicle 必須具有setManufacturer您聲明的方法。



查看完整回答
反對 回復 2023-09-08
?
守候你守候我

TA貢獻1802條經驗 獲得超10個贊

考慮一下:


class NotBicycle implements Vehicle { ... }


interface VehicleInterface {

? ? public function create(Vehicle $vehicle);

}


class BicycleService implements VehicleInterface {

? ? public function create(Bicycle $bicycle) {

? ? ? ? $bicycle->setManufacturer('Some company'); // Common for all Vehicle objects

? ? ? ? $bicycle->addSaddle(); // Common only for Bicycle objects

? ? }

}


function createVehicle(VehicleInterface $service, Vehicle $vehicle) {

? ? $service->create($vehicle);

}

$service = new BicycleService();

$vehicle = new NotBicycle();

createVehicle($service, $vehicle);

即使你以某種方式只能接受Bicycle其中的一個BicycleService,createVehicle($service, $vehicle)仍然會起作用,因為VehicleInterface有一個方法create(Vehicle $vehicle)。因此,為了讓它按照您想要的方式工作,您需要從根本上打破界面的本質。


您唯一真正的選擇是添加運行時類型檢查。就像例如


class BicycleService implements VehicleInterface {

? ? public function create(Vehicle $bicycle) {

? ? ? ? if (!$bicycle instance of Bicycle) {?

? ? ? ? ? ?throw new TypeError('Expected Bicycle but got '.get_class($bicycle));?

? ? ? ? }

? ? ? ? $bicycle->setManufacturer('Some company'); // Common for all Vehicle objects

? ? ? ? $bicycle->addSaddle(); // Common only for Bicycle objects

? ? }

}

您嘗試做的事情稱為協變方法參數類型,在大多數面向對象的編程語言中是不允許的,因為它違反了里氏替換原則


查看完整回答
反對 回復 2023-09-08
?
30秒到達戰場

TA貢獻1828條經驗 獲得超6個贊

Bicycle您需要刪除帶有 的類型Vehicle。你可能需要檢查if ($bicycle instanceof Bicycle)

抽象層次太抽象了。

查看完整回答
反對 回復 2023-09-08
?
慕尼黑的夜晚無繁華

TA貢獻1864條經驗 獲得超6個贊

您需要將您的Vehicle類傳遞給它,然后用于instanceof檢查接口。在下面的例子中,我更改了命名約定。


interface Vehicle {

    public function setSpeedLimit(Float $limit) : Car;

    public function setManufacturer(String $manufacturer) : MethodOfTransport;

}


interface NonVehicle {

    public function addSaddle() : Bicycle;

    public function setManufacturer(String $manufacturer) : MethodOfTransport;

}


abstract class MethodOfTransport

{

    public function setManufacturer(String $manufacturer) : MethodOfTransport { return $this; }

}


class Bicycle extends MethodOfTransport implements NonVehicle

{

查看它在 3v4l.org 上的運行情況。


}


class Car extends MethodOfTransport implements Vehicle

{

    public function setSpeedLimit(Float $limit) : Car { return $this; }

}


$b = new Bicycle();

$c = new Car();

如前所述,我消除了命名約定的一些混亂,因為 aBicycle不是 aVehicle而是 a MethodOfTransport。


interface VehicleServiceInterface

{

    # Change the return DataType to MethodOfTransport if Vehicle implements multiple classes

    public function create(MethodOfTransport $t) : Car;

}


class VehicleService implements VehicleServiceInterface

{

    public function create(MethodOfTransport $t) : Car

    {

        if (!$t instanceof Vehicle)

            throw new Exception( 'Cannot create a Vehicle on a NonVehicle instance.' );

            

        $t->setManufacturer( 'Foo' )->setSpeedLimit( 140 );

        return $t;

    }

}


$c = (new VehicleService())->create( $c ); // Works

$b = (new VehicleService())->create( $b ); // Throws Exception

和Car都是Bicyclea MethodOfTransport,但是,一個是 a Vehicle,另一個是 a NonVehicle。兩者都可以傳遞到方法中,但我們可以使用 來確保它是正確的類型instanceof。


但是,您可以將返回類型設置為方法的返回類型,create因為Car我們Vehicle在本例中僅過濾實例。如果您有多個Vehicle已實現的類,請將其更改為返回MethodOfTransport


查看它在 3v4l.org 上的運行情況。



查看完整回答
反對 回復 2023-09-08
  • 4 回答
  • 0 關注
  • 179 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號