2013-04-20 3 views
2

Предположим, что у меня есть абстрактный класс Car и есть x конкретных классов (RedCar, BlueCar ...), которые расширяют класс Car. Тогда у меня есть класс Garage, у которого есть автомобили Car [].Java-отслеживание типов объектов

Я хочу написать логический метод для класса Garage, который будет проходить через автомобили и возвращает true, если найден поиск автомобиля (один из конкретного типа (RedCar, BlueCar ..), переданный как параметр), в противном случае возвращает 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), добавить свойство к классу автомобилей, который будет содержать константу из перечисления и сравнить ее на основе этого?

Что-то вроде этого:

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

оба метода будут работать одинаково, на мой взгляд, –

+0

да, они будут, но я просто хочу знать, какой путь более профессиональен и как эта ручка опытных программистов – user10099

+0

Вы должны хранить их в разных коллекциях, если вы хотите проверить/поиск по типу класса. –

ответ

2

Если все подклассы не добавляют какое-либо состояние в базовый класс и не изменяют или не добавляют поведение путем добавления или переопределения методов в/базового класса, то у вас не должно быть подклассов. Достаточно иметь класс Car с атрибутом type.

Если у подкласса есть все основания для существования, тогда вы действительно можете использовать перечисление, но это не позволит добавить какой-либо другой тип автомобиля (без изменения перечисления).

Наличие метода, который ищет конкретный тип автомобиля, выглядит как запах дизайна для меня. Вероятно, это означает, что класс Car недостаточно полиморфен: instanceof и casts не очень OO.

+0

Ну, это просто очень упрощенный пример. В моем реальном проекте подклассы более надежны, они меняют состояние базового класса и методы переопределения. Реальная проблема заключается не только в автомобилях (речь идет о датчиках и конкретных типах датчиков), я должен был упомянуть об этом. Во всяком случае, мне не нравится первое (с экземпляром) решение, поэтому я прошу лучшего. Итак, мое второе решение, предполагающее, что у всех подклассов есть основания для существования, хорошо и OO дружелюбно? – user10099

1

Если вы определенно придерживаетесь того, чтобы разные цвета автомобиля были подтипами, я бы сказал, что ваша первая версия лучше - ваша вторая будет включать обновление перечисления каждый раз, когда вы добавляете новый тип автомобиля и включаете много copy-and-paste для кодирования конструкторов.

Однако я бы рекомендовал, чтобы если вы хотите найти гараж для определенных цветов автомобиля, имеет смысл иметь цвет как свойство автомобиля, а не проверять тип автомобиля. Во втором примере код выглядит «чище», поскольку вы не используете отражение, но в основном вы получаете дублированную информацию, поскольку цвет автомобиля представлен как по типу, так и по свойству CarType. Просто наличие одного типа автомобилей с цветовым значением сделает этот код намного короче и аккуратнее. Хотя, сказав это, я не знаю, что вы в конечном итоге хотите сделать с этим, поэтому ваш подход к подтипам все же может быть лучшим - возьмите то, что я говорю с щепоткой соли.

+0

Ну, это просто очень упрощенный пример. В моем реальном проекте подклассы более надежны, они меняют состояние базового класса и переопределяют методы, поэтому я не могу заменить их одним свойством. Проблема, с которой я имею дело, - это использовать refleciton или добавить свойство типа и сравнить его с базой. И я не против много копировать и вставлять, я просто хочу иметь чистый, красивый и OO-код. – user10099

1

Решение для перечисления, которое вы отправили, будет работать только в том случае, если вы хотите подтвердить, что автомобиль определенного типа найден. Не сам конкретный автомобильный объект. Кроме того, если ваши подклассы Car не имеют никакой разницы, кроме переменной типа, вам, вероятно, не нужны подклассы.

Первый метод выглядит хорошо, и может быть сокращено (немного), как это:

public boolean hasCar(Class<? extends Car> c) { 
    for (Car car : this.cars) { 
     if (c.isInstance(car) { 
      return true; 
     } 
    } 
    return false; 
} 
+0

Автомобильные подклассы имеют отличия, они должны быть объявлены в собственном классе. Но спасибо, я не знал о таких циклах, как это – user10099

0

Другой подход можно использовать, передавая объект фильтра и просить сам автомобиль, если он соответствует фильтру.информация об импорте фильтра может зависеть от вашего примера реальной жизни (и даже может сравниться с помощью instanceof()), но в упрощенном примере, который вы даете, это может быть строка или перечисление, указывающее цвет, который вы ищете , что-то вроде

public class CarFilter() 
{ 
String Color; 
} 

В базовом классе автомобиля у вас есть метод:

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

В производном классе RedCar метод может быть implemnted так:

public boolean matchesFilter(CarFilter filter) 
{ 
return filter.Color == "red"; //MAYBE case insensitive? 
} 
0

Чтобы ответить на этот вопрос, Я должен спросить себя, который предлагает самую легкую расширяемость? Я бы сказал, первая реализация.

Смежные вопросы