1

设想

这绝不是真实的,所以以一粒盐为例。这是一种传达场景的简单方法。话虽如此,假设我们有以下类定义。

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

class VehicleDescription {
   ...
}

class TruckDescription extends VehicleDescription implements iVehicle {
  ... 
}

class CarDescription extends VehicleDescription implements iVehicle {
  ...
}

问题

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

编辑-恐怕 我对我的例子有点含糊。我很抱歉。这两种描述或多或少是不同的数据结构,而不是字符串。一个可能返回一个表示详细描述的数组,长度为 3 列,另一个可能返回一个更基本的描述表,包含 2 列

4

4 回答 4

2

要么你对这两种情况都使用一种方法,并给它一个参数来确定它应该如何表现,例如

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 {
    // ...
}

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

于 2013-05-15T21:56:58.223 回答
1

一个接口可以被认为是一个契约。任何实现该接口的类都保证它将提供指定的功能。

但是,这完全取决于实现类如何实际执行此操作。在您的示例中TruckDescriptionCarDescription可能出于各种原因需要返回不同的描述格式,因此getDescriptionFormat1()&getDescriptionFormat2()以不同的方式实现。

基本上这意味着您可能只需要getDescriptionFormat()在接口中,然后实现类可以根据需要实现该功能。

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

于 2013-05-15T22:00:31.697 回答
1

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

编辑

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

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

于 2013-05-15T21:52:07.257 回答
0

这是我将如何解决这个问题。

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 由于它被定义为最终的)

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

于 2013-05-15T22:15:54.407 回答