Шаблон разработки: Полиморфизм для списка объектов

Предположим, что у меня есть класс A и A1, A2 наследовался A. Существует 2 функции:

List<A1> getListA1(){...}
List<A2> getListA2(){...}

Теперь я хочу сделать что-то подобное и A1 и A2 в другой функции

public void process(List<A>){...}

Если я хочу передать экземпляр или ListA1 или ListA2, конечно, типы не соответствуют, потому что компилятор не позволяет приведению из Списка <A1> Перечислять <A>. Я не могу сделать чего-то вроде этого:

List<A1> listA1 = getListA1();
List<A> newList = (List<A>)listA1; //this is not allowed.

Таким образом, что лучший подход к процессу ()? Там какой-либо путь состоит в том, чтобы сделать это универсальным способом, а не написать подобный код, чтобы и Перечислить и Перечислить?

7
задан zs2020 28 April 2010 в 04:02
поделиться

5 ответов

Хотя я не могу предложить java-решение, вот некоторые из них для C # ...

Если вы можете изменить подпись процесса для принятия IEnumerable ...

public void Process(IEnumerable<A> myList) { ... }

то в C # 4.0 все будет просто работать благодаря улучшенной поддержке ко- и контравариантности.

Если вы работаете в C # 3.0, вы можете ввести параметр универсального типа в метод:

public void Process<T>(List<T> myList) where T : A { ... }

Затем вы можете вызвать передачу либо List, либо List, и параметр универсального типа будет привязан соответствующим образом. Обратите внимание, что вам не часто нужно указывать его напрямую, поскольку определение типа обычно дает вам то, что вам нужно.

Если это не подходит, вы можете преобразовать список с помощью метода расширения Cast из Enumerable:

public void Process(List<A> myList) { ... }

var someList = getListA1();
Process( someList.Cast<A>());
8
ответ дан 6 December 2019 в 14:01
поделиться
import java.util.*;

class A {
    int x;
}

class A1 extends A {
    int y;
}

class A2 extends A {
    int z;
}

public class polymorphisimForListOfObjects {
    static void foo(List<? extends A> l) { // probably can't modify the list
        System.out.println(l);
    }

    public static void main(String[] arguments) {
        A1[] a1 = { new A1(), new A1() };
        A2[] a2 = { new A2(), new A2() };
        List<A1> l1 = Arrays.asList(a1);
        List<A2> l2 = Arrays.asList(a2);
        foo(l1);
        foo(l2);
    }

}
1
ответ дан 6 December 2019 в 14:01
поделиться

Используйте подстановочный знак:

public void process(List<? extends A>){...}
6
ответ дан 6 December 2019 в 14:01
поделиться

Используйте метод расширения Cast из IEnumerable.

0
ответ дан 6 December 2019 в 14:01
поделиться

Не могут getListA1 () и getListA2 () просто вернуть типы списков в первом экземпляре?

List<A> getListA1(){...}
List<A> getListA2(){...}
0
ответ дан 6 December 2019 в 14:01
поделиться