2

假设我有抽象类 Car,并且有 x 个扩展类 Car 的具体类(RedCar、BlueCar ...)。然后我有具有属性 Car[] cars 的类 Garage。

我想为 Garage 类编写一个布尔方法,该方法将遍历汽车并在找到搜索汽车(作为参数传递的具体类型之一(RedCar、BlueCar..))时返回 true,否则返回 false。

最好的方法是什么?

现在,我有这样的事情:

public boolean hasCar(Class<? extends Car> c) {
    for (int i = 0; i < this.cars.length; i++) {
        if (c.isInstance(this.cars[i])) {
            return true;
        }
    }
    return false;
}

但是如果我创建一个包含所有可能的 Car 类型(Car 的子类)的枚举,向 Car 类添加一个属性,它将保存枚举中的常量并基于它进行比较,这不是更好吗?

像这样的东西:

public enum CarType{
    RED_CAR, BLUE_CAR
}

public abstract class Car{
    public CarType type;
    Car(CarType type){
        this.type = type;
    }
}

public class RedCar extends Car{
    public RedCar(){
        super(CarType.RED_CAR);
    }
}

public class BlueCar extends Car{
    public BlueCar(){
        super(CarType.BLUE_CAR);
    }
}

public class Garage{
    private Car[] cars;
    public boolean hasCar(CarType type) {
        for (int i = 0; i < this.cars.length; i++) {
            if(this.cars[i].type == type){
                return true;
            }
        }
        return false;
    }
}

哪一个是更好的方法?

4

5 回答 5

2

如果所有子类都没有向基类添加任何状态,并且没有通过向基类添加或覆盖方法来更改或添加行为,那么您不应该有子类。只需拥有一个带有type属性的 Car 类就足够了。

如果子类有充分的理由存在,那么您确实可以使用枚举,但这会阻止添加任何其他类型的汽车(也不会更改枚举)。

拥有一种搜索特定类型汽车的方法对我来说似乎是一种设计气味。这可能意味着 Car 类不够多态:instanceof 和 casts 不是很面向对象。

于 2013-04-20T17:32:04.703 回答
1

您发布的枚举解决方案仅在您想确认找到某种类型的汽车时才有效。不是特定的汽车对象本身。此外,如果您的 Car 子类除了类型变量之外没有任何区别,您可能不需要子类。

第一种方法看起来不错,并且可以像这样缩短(一点):

public boolean hasCar(Class<? extends Car> c) {
    for (Car car : this.cars) {
        if (c.isInstance(car) {
            return true;
        }
    }
    return false;
}
于 2013-04-20T17:40:18.393 回答
1

如果您肯定坚持使用不同颜色的汽车作为子类型,我会说您的第一个版本更好 - 您的第二个版本将涉及每次添加新类型汽车时更新枚举并且涉及大量复制和 -为构造函数粘贴样式编码。

但是,我建议如果您想在车库中搜索某些颜色的汽车,将颜色作为汽车的属性而不是检查汽车的类型是有意义的。在您的第二个示例中,代码看起来“更干净”,因为您没有使用反射,但是您基本上得到了重复的信息,因为汽车的颜色由它的类型和它的 CarType 属性表示。简单地拥有一个带有 Color 值的 Car 类型会使这段代码更短更整洁。尽管如此,我不知道你最终想用这个做什么,所以你拥有亚型的方法可能仍然是最好的 - 拿我说的话加点盐。

于 2013-04-20T17:32:37.467 回答
0

您可以使用的另一种方法是传递一个过滤器对象并询问汽车本身是否与过滤器匹配。过滤器的实现细节可能取决于您的实际示例(甚至可以使用instanceof()进行比较),但在您给出的简化示例中,它可能是指定您正在寻找的颜色的字符串或枚举。就像是

public class CarFilter()
{
String Color;
}

在汽车的基类中,您有一个方法:

public boolean matchesFilter(CarFilter filter){} //maybe abstract?

在派生类 RedCar 中,该方法可能像这样实现:

public boolean matchesFilter(CarFilter filter)
{
 return filter.Color == "red"; //MAYBE case insensitive?
}
于 2013-04-20T18:06:28.080 回答
0

要回答这个问题,我必须问自己哪个提供了最简单的可扩展性?我会说第一个实现。

于 2013-04-21T02:24:39.313 回答