Я задал аналогичный вопрос в другом сообщении (Как реализовать метод из производного класса, который не требует приведения), но это немного более конкретно. Предположим, у меня есть 3 класса: Автомобиль, Автомобиль, Кабриолет. Автомобиль расширяет автомобиль, а кабриолет расширяет автомобиль. Мне нужен метод для каждого класса, который возвращает список, не требующий приведения во время выполнения. Подумав, я считаю, что это невозможно, но я также хочу услышать ваше мнение

public class Vehicle {
    public List<? extends Vehicle> getList() {
        return new ArrayList<Vehicle>();
    }
}

public class Car extends Vehicle {
    @Override
    public List<? extends Car> getList() {
        return new ArrayList<Car>();
    }
}

public class Convertible extends Car {
    @Override
    public List<? extends Convertible> getList() {
        return new ArrayList<Convertible>();
    }
}

Чтобы не использовать приведение, мне пришлось бы возвращать определенный тип элемента в списке (List<Convertible>), но тогда, если бы я хотел расширить класс Convertible, я больше не мог бы этого делать.

Есть ли способ обойти эту ситуацию?

3
gabyk00 13 Дек 2014 в 23:47
Не могли бы вы заставить Vehicle принять аргумент универсального типа, а затем использовать этот аргумент для типа списка?
 – 
Dioxin
13 Дек 2014 в 23:50
2
Вам нужно бросить? Разве вы не можете просто использовать List<? extends Convertible> как тип переменной, хранящей возвращаемое значение.
 – 
aioobe
13 Дек 2014 в 23:55

2 ответа

Лучший ответ

Если вы хотите уметь писать

List<Vehicle> list1 = new Vehicle().getList();
List<Car> list2 = new Car().getList();
List<Convertible> list3 = new Convertible().getList();

Вам не повезло. List<Car> не является подтипом List<Vehicle>, поэтому возвращаемые типы несовместимы. Вы можете избавиться от предупреждений компилятора, используя свой код, написав, например,

List<Car> list = new ArrayList<Car>(new Car().getList());

Однако я не совсем уверен, почему метод getList() должен быть унаследован. Если вы всегда знаете тип Vehicle, для которого вызываете метод, вы также можете иметь отдельный метод в каждом классе, называемый getVehicleList(), getCarList() и getConvertibleList(), возвращает List<Vehicle>, List<Car> и List<Convertible> соответственно.

1
Paul Boddington 14 Дек 2014 в 01:03

Ты можешь написать

public class Vehicle<V extends Vehicle> {
    public List<V> getList() {
        return new ArrayList<V>();
    }
}

public class Car<C extends Car> extends Vehicle<C> {
}

public class Convertible extends Car<Covertible> {
}
5
Peter Lawrey 13 Дек 2014 в 23:58