2010-04-28 14 views
7

Supponiamo che io sono una classe A e A1, A2 eredita da A. Ci sono 2 funzioni:Design Pattern: polimorfismo per la lista di oggetti

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

Ora voglio fare qualcosa di simile a entrambi A1 e A2 in un'altra funzione

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

Se voglio passare l'istanza di una ListA1 o ListA2, naturalmente, i tipi non corrisponde perché il compilatore non consente coercizione dalla lista < A1> to List < a >. Non posso fare qualcosa del genere:

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

Quindi qual è l'approccio migliore al processo()? Esiste un modo per farlo in modo universale piuttosto che scrivere il codice simile sia per List che per List?

risposta

8

Mentre non posso offrire una soluzione Java, ecco alcuni per C# ...

Se è possibile modificare la firma del processo di accettare IEnumerable ...

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

quindi, in C# 4.0, tutto funzionerà, grazie al supporto migliorato per co- e contro-varianza.

Se si lavora in C# 3.0, è possibile introdurre un parametro di tipo generico al metodo:

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

Quindi, è possibile chiamare il passaggio sia List o List e il parametro di tipo generico si legano di conseguenza. Si noti che spesso non è necessario specificarlo direttamente, poiché il tipo di inferenza di solito ti dà quello che ti serve.

Se questo non va bene, è possibile convertire l'elenco utilizzando il metodo Cast estensione da Enumerable:

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

var someList = getListA1(); 
Process(someList.Cast<A>()); 
6

Utilizzare un jolly legato:

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

Utilizzare il metodo Cast estensione da IEnumerable.

0

Can not getListA1() e getListA2() è sufficiente restituire i tipi di elenco in prima istanza?

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

ho pensato a questo prima. Il problema è che questi 2 metodi sono usati altrove, e ho cambiato tutto il posto correlato. – zsong

1
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); 
    } 

} 
+0

Grazie! Ti ho appena dato un voto. – zsong

0

Prova questo esempio:



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 
    } 
}