【问题标题】:How to handle abstract property in Java?如何在 Java 中处理抽象属性?
【发布时间】:2018-06-01 16:52:56
【问题描述】:

假设我想要一个 MyClass 类,其中包括一个代表车辆的属性。

车辆可以是汽车或摩托车。

如果是汽车,我希望能够取回它的方向盘。

编辑:我的基本主张是摩托车没有方向盘,所以我想避免在摩托车类中使用 getSteeringWheel 之类的东西。

我看到了两种解决方案:

  1. 由两个类扩展的抽象 Vehicle 类:汽车和摩托车

问题在于,从 MyClass 对象中,要检索方向盘的类型,我必须执行以下操作:

Vehicle vehicle = getVehicle();
if (vehicle instanceof Car) {
    SteeringWheel steeringWheel = ((Car) vehicle).getSteeringWheel();
}

我认为这不是很好。

  1. 包含所有内容的具体 Vehicle 类

然后我会做这样的事情:

Vehicle vehicle = getVehicle();
if (VehicleTypeEnum.CAR.equals(vehicle.getType())) {
    SteeringWheel steeringWheel = vehicle.getSteeringWheel();
}

但是 Vehicle 将是一个错误的类,因为如果对象的类型是 MOTORCYCLE,那么 getSteeringWheel() 方法没有多大意义。

哪个更好?还有其他解决方案吗?谢谢!

【问题讨论】:

  • 你也可以使用接口HasSteeringWheel 并且只在有方向盘的类上实现它
  • 我仍然需要在 Motorcycle 类中实现 hasSteeringWheel 方法,我想避免这种情况,因为我认为摩托车没有方向盘。
  • 您能否备份并解释为什么可以与Vehicle 有效交互的代码有时会关心CarSteeringWheelVehicle 是一种抽象,它们应该专注于操作,而不是属性。也就是说,您应该告诉车辆(或其驾驶员)去哪里,并让它适当地解释信息,而不是拿到汽车的方向盘并操纵它。司机将使用汽车的方向盘,骑手将使用她的摩托车车把,计算机将适当地设置开关以引导火车到达目的地,等等。
  • 你能不能在摩托车上实现它并返回null。那么你只是执行一个空检查?也许这很糟糕
  • @erickson 我明白你的意思,我会尝试看看如何在我的情况下应用它。谢谢!

标签: java casting properties abstract instanceof


【解决方案1】:

避免使用instanceof,因为它会使用break your OOP design。相反,找到汽车和摩托车的共同点。两者都有一个负责转向的部分。将其提取到超类中,并在子类中实现实际的转向。

public abstract class Vehicle {
   public abstract Steer getSteer();
}



public abstract class Steer {
   public abstract left();
   public abstract right();
}


public class Car extends Vehicle {
    @Override
    public SteeringWheel getSteer() {
        return wheel;
    } 
}

public class Motorcycle extends Vehicle {
    @Override
    public SteeringBar getSteer() {
        return bar;
    } 
}

(作为非母语,我不确定 'steer' 是否真的是一个英文名词)

【讨论】:

  • 也许我的例子不好,但我的基本主张是摩托车没有方向盘,所以我想避免在摩托车类中使用 getSteeringWheel 之类的东西。
  • @Wenneguen 这个答案也符合我的建议。任何与Vehicle 交互的东西都可以这样做,而不必向下转换为子类型。
  • @erickson 我的错,我误读了你的答案。但是,您仍然设法找到了一个相当于方向盘(转向杆)的东西,这证明了我的例子有多糟糕。但是,您将如何处理汽车拥有而摩托车没有的东西呢?
  • @Wenneguen 什么是试图访问方向盘,他们会用它做什么?我喜欢这个答案,因为它关注的是操作(方法)而不是数据。您可以获得“Steer”并向其发送左右消息;不管是方向盘、车把还是滑翔伞的控制线。即使是没有转向机构的火车,您也可以返回一个什么都不做的NoOpSteer
【解决方案2】:

对不起,如果问题措辞不当,但我认为在您的帮助下,我设法解决了我的问题。目前我有这样的事情:

public class MyClass {

private Vehicle vehicle;

public void doStuff() {

    doNonVehicleStuff();

    Vehicle vehicle = getVehicle();

    doRegularStuff(vehicle);

    if (vehicle instanceof Car) {
        SteeringWheel steeringWheel = ((Car) vehicle).getSteeringWheel();
        doSteeringWheelStuff(steeringWheel);
    }
}

但实际上我应该这样做:

public void doStuffWithVehicle() {    

    doNonVehicleStuff();

    getVehicle().doStuff();
}

使用Car 覆盖doStuff 方法以在regularStuff 之外包含doSteeringWheelStuff

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-15
    • 2012-10-01
    • 1970-01-01
    • 2021-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多