1

我有以下问题。假设我有以下两个课程:Bicycle a MountainBike。在 MountainBike 的标题中,我声明:public class MountainBike extends Bicycle. MountainBike 类添加了 Bicycle 中不存在的两个字段。因为我一一添加属性(因为我正在使用数据库),所以没有构造函数,而是一个函数,它设置给定字符串标识符和值的属性。我知道可能并非所有属性都已设置并且可能为空,但这对我来说没问题。

现在问题如下。在给定的一点上,我知道它是什么类型的自行车,它是其中一个领域。我想做的是:一旦我知道这个 Bicycle 对象实际上是 MountainBike,我想将它转换为 MountainBike: MountainBike mb = (MountainBike) bicycle,但是这会导致运行时 java.lang.ClassCastException: Bicycle cannot be投射到山地自行车。

我确信这是可能的(不使用将整个自行车作为参数的构造函数)。我怎样才能做到这一点?

谢谢!

赫克托

4

3 回答 3

6

就像 Jon Skeet 在他的评论中所说的那样,如果它不是 aMountainBike并且只是一个 plain ,你就不能施放它Bicycle。您可以做的是创建一个构造函数,MountainBike该构造函数将Bicycle其作为参数:

public MountainBike(Bicycle bicycle) {
    // Copy bicycle's properties
}

而是调用它:

MountainBike mb = new MountainBike(Bicycle bicycle);

如果MountainBike由于某种原因无法修改类,还可以创建static工厂方法:

public class MountainBikeFactory {

    public static MountainBike createMountainBike(Bicycle bicycle) {
        MountainBike mb = new MountainBike();
        // Copy bicycle's properties
        return mb;
    }
}

并称之为:

MountainBike mb = MountainBikeFactory.create(bicycle);

编辑:查看您发布的作为对该问题的评论的信息后,您似乎可以尝试构建器模式。构建器将包含所有属性作为变量(是的,它将很长,有 100 多个变量),当您从文件中发现属性时,将它们设置在构建器上。然后,最后,当您调用构建器的build()方法时,让它解析要创建的自行车类型,并使用多态性来处理您创建的自行车的属性组。

例如:

public class BikeBuilder {
    private String model;
    private String wheelSize;
    private String shocks;
    private String racingHandleBarType;

    // returns "this" so you can chain calls, common in builders, not necessary
    public BikeBuilder setModel(String model) {
        this.model = model;
        return this;
    }

    // Other setters

    public Bike build() {
        Bike bike;
        // Determine which kind of bike it is and create it
        if (shocks != null) {
            bike = new MountainBike();
            handleMountainBike((MountainBike) bike);
        } else if (racingHandleBarType != null) {
            bike = new RacingBike();
            handleRacingBike((RacingBike) bike);
        } else {
            bike = new Bike();
        }
        handleCommonAttributes(bike);
        return bike;
    }

    // All bikes have these attributes
    private void handleCommonAttributes(Bike bike) {
        bike.setModel(model);
        bike.setWheelSize(wheelSize);
    }

    private void handleMountainBike(MountainBike bike) {
        bike.setShocks(shocks);
    }

    private void handleRacingBike(RacingBike bike) {
        bike.setRacingHandleBarType(racingHandleBarType);
    }
}

这使您可以即时构建自行车并在读取文件结束时而不是开始时决定其类型。它充当一种容器。如果您有多种扩展类型,Bike您可以为它们创建新方法。这至少会让你开始。

于 2013-02-11T18:32:39.223 回答
2

如果您怀疑施法之前可能会失败检查:

if (bike instanceof MountainBike) {
    MountainBike mb = (MountainBike) bike
} else {
    String msg = "Wrong bike, expected Mountainbike but was:" + bike.getClass();

    System.out.println(msg);
    throw new IllegalArgumentException(msg);
}
于 2013-02-11T18:32:31.327 回答
2

您不能仅仅因为 MountainBike 扩展 Bike 就将 Bike 转换为 MountainBike。这是一个例子:

Bike bike = new MountainBike();
MountainBike mb = (MountainBike) bike; //works

Bike bike = new Bike();
MountainBike mb = (MountainBike) bike; //ClassCastException
于 2013-02-11T18:36:44.540 回答