设计模式:对象列表的多态性

zs2*_*020 7 c# java design-patterns

假设我有一个A类,A1,A2继承自A.有2个函数:

List<A1> getListA1(){...}
List<A2> getListA2(){...}
Run Code Online (Sandbox Code Playgroud)

现在我想在另一个函数中执行类似于A1和A2的操作

public void process(List<A>){...}
Run Code Online (Sandbox Code Playgroud)

如果我想传递ListA1或ListA2的实例,当然类型不匹配,因为编译器不允许从List <A1>到List <A>的强制.我做不到这样的事情:

List<A1> listA1 = getListA1();
List<A> newList = (List<A>)listA1; //this is not allowed.
Run Code Online (Sandbox Code Playgroud)

那么这个过程的最佳方法是什么()?有没有办法以通用的方式做到这一点,而不是将类似的代码写入List和List?

Bev*_*van 8

虽然我不能提供java解决方案,但这里有一些用于C#...

如果你可以改变Process的签名来接受IEnumerable ......

public void Process(IEnumerable<A> myList) { ... }
Run Code Online (Sandbox Code Playgroud)

然后,在C#4.0中,由于对共同和反差的改进支持,一切都将正常工作.

如果您使用的是C#3.0,则可以在方法中引入泛型类型参数:

public void Process<T>(List<T> myList) where T : A { ... }
Run Code Online (Sandbox Code Playgroud)

然后,您可以调用传递List或List,并且泛型类型参数将相应地绑定.请注意,您通常不必直接指定它,因为类型推断通常会为您提供所需的内容.

如果这不适合,您可以使用CastEnumerable中的扩展方法转换List :

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

var someList = getListA1();
Process( someList.Cast<A>());
Run Code Online (Sandbox Code Playgroud)


mat*_*t b 6

使用通配符绑定:

public void process(List<? extends A>){...}
Run Code Online (Sandbox Code Playgroud)