让我们说我有抽象类Car,并且有x个具体类(RedCar,BlueCar ......)扩展了类Car。然后我就有了车库,它有Car []车的属性。
我想写一个布尔方法,用于循环遍历汽车的类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;
}
}
哪一个是更好的方法?
答案 0 :(得分:2)
如果所有子类都没有向基类添加任何状态,并且不通过向基类添加或重写方法来更改或添加行为,那么您不应该有子类。只要拥有一个type
属性的Car类就足够了。
如果子类有充分的理由存在,那么你确实可以使用枚举,但这会阻止添加任何其他类型的汽车(也不会更改枚举)。
有一种搜索特定类型汽车的方法对我来说就像是一种设计气味。这可能意味着Car类的多态性不够:instanceof和casts不是很好OO。
答案 1 :(得分:1)
如果您肯定坚持使用不同颜色的汽车作为子类型,我会说您的第一个版本更好 - 您的第二个版本将涉及每次添加新型汽车并涉及大量复制时更新枚举并且为构造函数粘贴样式编码。
但是,我建议如果你想在车库搜索某些颜色的汽车,那么将颜色作为汽车的属性是有意义的,而不是必须检查汽车的类型。在您的第二个示例中,代码看起来“更干净”,因为您没有使用反射,但您基本上获得了重复信息,因为汽车的颜色由其类型和CarType属性表示。简单地使用具有Color值的单一Car类型将使该代码更短且更整洁。虽然有了这个说法,我不知道你最终想要做什么,所以你的子类型方法可能仍然是最好的 - 用一点点的盐来说话。
答案 2 :(得分:1)
您发布的枚举解决方案仅在您确定找到某个类型的汽车时才有效。不是特定的汽车对象本身。此外,如果您的Car子类除了类型变量之外没有任何区别,您可能不需要子类。
第一种方法看起来很好,可以像这样缩短(一点点):
public boolean hasCar(Class<? extends Car> c) {
for (Car car : this.cars) {
if (c.isInstance(car) {
return true;
}
}
return false;
}
答案 3 :(得分: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?
}
答案 4 :(得分:0)
要回答这个问题,我必须问自己哪个方面提供最简单的可扩展性?我会说第一次实现。