Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/232.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 确保类至少实现一个方法_Php_Oop - Fatal编程技术网

Php 确保类至少实现一个方法

Php 确保类至少实现一个方法,php,oop,Php,Oop,情景 这决不是真的,所以请恕我直言。这是一种表达场景的简单方式。话虽如此,假设我们有以下类定义 interface iVehicle { public function getDescriptionFormat1(); public function getDescriptionFormat2(); } class VehicleDescription { ... } class TruckDescription extends VehicleDescription im

情景

这决不是真的,所以请恕我直言。这是一种表达场景的简单方式。话虽如此,假设我们有以下类定义

interface iVehicle {
   public function getDescriptionFormat1();
   public function getDescriptionFormat2(); 
}

class VehicleDescription {
   ...
}

class TruckDescription extends VehicleDescription implements iVehicle {
  ... 
}

class CarDescription extends VehicleDescription implements iVehicle {
  ...
}
问题

CardDescription和TruckDescription类可以实现一种或两种描述格式。当只需要一个方法时,在两个类中重写这两个方法似乎是错误的。实施这种限制的正确方式是什么?或者,你可以尝试向我推销这是一个糟糕的设计决策

编辑-
恐怕我的例子有点太模糊了。我道歉。这两种描述或多或少是不同的数据结构,而不是字符串。一个可能返回一个表示详细描述的数组,长度为3列,另一个可能返回一个包含2列的更基本的描述表。您可能只需要使用一个getDescriptionFormat方法,并为VehicleDescription类的不同子类提供适当的实现

编辑

我刚刚阅读了您对问题的评论,这些类可以实现这两种方法。如果这是您想要的,那么您的示例已经可以了。您可以做的一件事是在VehicleDescription类中提供空的实现


至于如何确保在这个场景中至少实现一个方法,我认为这是不可能的,但是如果我错了,请纠正我:

您可能应该只使用一个getDescriptionFormat方法,并为VehicleDescription类的不同子类提供适当的实现

编辑

我刚刚阅读了您对问题的评论,这些类可以实现这两种方法。如果这是您想要的,那么您的示例已经可以了。您可以做的一件事是在VehicleDescription类中提供空的实现


至于如何确保在这种情况下至少实现其中一种方法,我认为这是不可能的,但如果我错了,请纠正我:

或者您对这两种情况都使用一种方法,并给它一个参数以确定其行为,例如

interface iVehicle {
    public function getDescription($Format);
}

class CarDescription extends VehicleDescription implements iVehicle {
    public function getDescription($Format) {
        switch ($Format) {
            case 1:
                // Do what needs to be done
                break;
            case 2:
                // Do what needs to be done
                break;
            default:
                throw new Exception('Error');
                break;
    }
}
或者您使用两个接口,并且该类为其实现适当的接口,或者同时实现这两个接口

interface iVehicle1 {
    public function getDescriptionFormat1();
}
interface iVehicle2 {
    public function getDescriptionFormat2();
}

// Let's skip forward

class CarDescription extends VehicleDescription implements iVehicle1, iVehicle2 {
    // ...
}

当然,在后一种情况下,您仍然必须使用不同的方法名称,以防该类将实现两个接口。

或者您对两种情况都使用一个方法,并为其指定一个参数以确定其行为方式,例如

interface iVehicle {
    public function getDescription($Format);
}

class CarDescription extends VehicleDescription implements iVehicle {
    public function getDescription($Format) {
        switch ($Format) {
            case 1:
                // Do what needs to be done
                break;
            case 2:
                // Do what needs to be done
                break;
            default:
                throw new Exception('Error');
                break;
    }
}
或者您使用两个接口,并且该类为其实现适当的接口,或者同时实现这两个接口

interface iVehicle1 {
    public function getDescriptionFormat1();
}
interface iVehicle2 {
    public function getDescriptionFormat2();
}

// Let's skip forward

class CarDescription extends VehicleDescription implements iVehicle1, iVehicle2 {
    // ...
}

当然,在后一种情况下,您仍然必须使用不同的方法名称,以防该类将实现两个接口。

一个接口可以被视为一个契约。实现该接口的任何类都保证它将提供指定的函数

然而,这完全取决于实现类如何实际做到这一点。在您的示例中,由于各种原因,TruckDescription和CardDescription可能需要返回不同的描述格式,因此以不同的方式实现getDescriptionFormat1和getDescriptionFormat2

基本上,这意味着您可能只需要在接口中使用getDescriptionFormat,然后实现类就可以根据需要实现该函数


听起来好像你应该标准化返回的内容。也许是一个可以封装描述的Format类?我现在只是猜测,因为我不知道任何细节,但我想这就是我要考虑的。

一个接口可以被视为一个合同。实现该接口的任何类都保证它将提供指定的函数

然而,这完全取决于实现类如何实际做到这一点。在您的示例中,由于各种原因,TruckDescription和CardDescription可能需要返回不同的描述格式,因此以不同的方式实现getDescriptionFormat1和getDescriptionFormat2

基本上,这意味着您可能只需要在接口中使用getDescriptionFormat,然后实现类就可以根据需要实现该函数


听起来好像你应该标准化返回的内容。也许是一个可以封装描述的Format类?我现在只是猜测,因为我不知道任何细节,但我想这就是我要考虑的。

以下是我将如何解决这个问题

interface Describable {
   public function getDescription(); 
}

interface Sellable {
    public function getPrice();
}

// abstract class - can't create an instance but can hold shared methods and property definitions
abstract class Vehicle implements Describable, Sellable {
    abstract public function getDescription();

    // this can't be overloaded
    final public function getPrice(){
        // code for get price
    }
    public function getColorOptions(){
        // this can be overloaded
    }
}

// concrete class that just uses the abstracts' definitions
class Car extends Vehicle {
    public function getDescription(){
        // overload for cars
    }
}

// concrete class that overloads one of the properties
class Truck extends Vehicle {
    public function getDescription(){
        // overload for trucks
    } 
}


class FlyingCar extends Car {
    public function getDescription(){
        // Flying cars need a whole new description
    }

}
基本上,这显示了一个必须重载getDescription的方法,因为它被定义为抽象的

一个不能因为getPrice被定义为final而被重载的函数


以及在抽象上定义的一个,您可以重载或使用默认实现

以下是我将如何解决这个问题

interface Describable {
   public function getDescription(); 
}

interface Sellable {
    public function getPrice();
}

// abstract class - can't create an instance but can hold shared methods and property definitions
abstract class Vehicle implements Describable, Sellable {
    abstract public function getDescription();

    // this can't be overloaded
    final public function getPrice(){
        // code for get price
    }
    public function getColorOptions(){
        // this can be overloaded
    }
}

// concrete class that just uses the abstracts' definitions
class Car extends Vehicle {
    public function getDescription(){
        // overload for cars
    }
}

// concrete class that overloads one of the properties
class Truck extends Vehicle {
    public function getDescription(){
        // overload for trucks
    } 
}


class FlyingCar extends Car {
    public function getDescription(){
        // Flying cars need a whole new description
    }

}
基本上,这显示了一个必须重载getDescription的方法,因为它被定义为抽象的

不能超载的 getPrice的定义是最终的


以及在抽象上定义的一个,您可以重载或使用默认实现

你可以在其中使用特征和抽象方法。所以卡车将使用truckTrait,并且必须只实现其方法,而汽车将只使用carTrait,并且必须实现其方法。但这看起来也很难看。对不起,如果我不清楚的话-这两种格式都可以通过CardDescription和TruckDescription实现。那么,为什么不在车辆描述中声明它们并在必要时实现呢?@MaximKhan Magomedov确实是一个选项,但是,我没有办法强制将来的类来实现其中一个方法。错误或警告会很好。您还可以在其子级必须实现方法的类中的方法中抛出异常或触发错误。您可以在其中使用traits和抽象方法。所以卡车将使用truckTrait,并且必须只实现其方法,而汽车将只使用carTrait,并且必须实现其方法。但这看起来也很难看。对不起,如果我不清楚的话-这两种格式都可以通过CardDescription和TruckDescription实现。那么,为什么不在车辆描述中声明它们并在必要时实现呢?@MaximKhan Magomedov确实是一个选项,但是,我没有办法强制将来的类来实现其中一个方法。一个错误或警告就好了。您还可以在类中的方法中抛出一个异常或触发错误,该类的子类必须实现该方法。我喜欢第二个示例。到目前为止,它和我要找的差不多。我只需要检查类_是否实现了三个不同接口中的一个。我喜欢第二个示例。到目前为止,它和我要找的差不多。我只需要检查类_是否实现了三个不同接口中的一个。所有这些都是正确的,但我担心我的示例有点太模糊了。我道歉。这两种描述或多或少是不同格式的数据,而不是字符串。一个可能返回一个数组,表示3列长度的详细描述,另一个可能返回一个包含2列的更基本的描述表。那么您可能应该标准化返回的内容?也许是一个可以封装描述的Format类?我现在只是猜测,因为我不知道任何细节,但我想这就是我要考虑的。这都是真的,但我恐怕我的例子有点太模糊了。我道歉。这两种描述或多或少是不同格式的数据,而不是字符串。一个可能返回一个数组,表示3列长度的详细描述,另一个可能返回一个包含2列的更基本的描述表。那么您可能应该标准化返回的内容?也许是一个可以封装描述的Format类?我现在只是猜测,因为我不知道任何细节,但我想这是我会考虑的。