Design pattern: polymorphism for a list of objects

Suppose I have a class A, and A1, A2 inherits from A. There are 2 functions:

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

Now I want to do something similar to A1 and A2 in another function

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

If I want to pass an instance of ListA1 or ListA2, of course, the types do not match, because the compiler does not allow coercion from List <A1> for list <A>. I can not do something like this:

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

So what is the best approach to process ()? Is there a way to do this in a universal way, rather than writing similar code to a list and list?

+7
java c # design-patterns
source share
6 answers

While I cannot offer a Java solution, here are some of them for C # ...

If you can change the process signature to accept IEnumerable ...

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

then everything will work in C # 4.0, thanks to improved support for companion and opposite variance.

If you work in C # 3.0, you can enter a generic parameter type in a method:

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

You can then invoke the transfer of a List or List, and the generic type parameter will be bound accordingly. Note that you do not often have to specify it directly, as the inferrence type usually gives you what you need.

If this doesn't work, you can convert the list using the Cast extension method from Enumerable:

 public void Process(List<A> myList) { ... } var someList = getListA1(); Process( someList.Cast<A>()); 
+8
source share

Use wildcard binding:

 public void process(List<? extends A>){...} 
+6
source share
 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
source share

Use the Cast extension method from IEnumerable.

0
source share

Can't getListA1() and getListA2() just return the list types in the first instance?

 List<A> getListA1(){...} List<A> getListA2(){...} 
0
source share

Try this example:

 using System.Collections.Generic; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { List myList; myList = GetMyList(MyListTypeEnum.MyList1); myList = GetMyList(MyListTypeEnum.MyList2); } public static List GetMyList(MyListTypeEnum tipo) { List result; result = new List(); switch (tipo) { case MyListTypeEnum.MyList1: List myList1 = GetMyList1(); foreach (var item in myList1) { result.Add((IMyList) item); } break; case MyListTypeEnum.MyList2: List myList2 = GetMyList2(); foreach (var item in myList2) { result.Add((IMyList) item); } break; } return result; } public static List GetMyList1() { List myList1 = new List(); myList1.Add(new MyList1 { Code = 1 }); myList1.Add(new MyList1 { Code = 2 }); myList1.Add(new MyList1 { Code = 3 }); return myList1; } public static List GetMyList2() { List myList2 = new List(); myList2.Add(new MyList2 { Name = "1" }); myList2.Add(new MyList2 { Name = "2" }); myList2.Add(new MyList2 { Name = "3" }); return myList2; } } public interface IMyList { } public class MyList1 : IMyList { public int Code { get; set; } } public class MyList2 : IMyList { public string Name { get; set; } } public enum MyListTypeEnum { MyList1, MyList2 } } 
0
source share

All Articles