2010-04-28 14 views
7

Supongamos que tengo una clase A y A1, A2 hereda de A. Hay 2 funciones:Diseño modelo: El polimorfismo de la lista de objetos

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

Ahora quiero hacer algo similar a A1 y tanto A2 en otra función

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

Si quiero pasar a la instancia de cualquiera de ListA1 o ListA2, por supuesto, los tipos no coincide porque el compilador no permite la coacción de la Lista < A1> < a la lista a >. No puedo hacer algo como esto:

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

Entonces, ¿cuál es el mejor enfoque para el proceso()? ¿Hay alguna forma de hacerlo de forma universal en lugar de escribir el código similar para la Lista y la Lista?

Respuesta

8

Aunque no puedo ofrecer una solución de Java, aquí están algunos para C# ...

Si puede alterar la firma del Proceso de aceptar IEnumerable ...

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

luego, en C# 4.0, todo funcionará, gracias al soporte mejorado para la contra-varianza y contra-variación.

Si está trabajando en C# 3.0, puede introducir un parámetro de tipo genérico para el método:

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

A continuación, puede llamar a pasar en ninguna lista o la lista y el parámetro de tipo genérico se unirá en consecuencia. Tenga en cuenta que a menudo no tiene que especificarlo directamente, ya que la inferrence de tipo generalmente le dará lo que necesita.

Si esto no se ajusta, podría convertir la lista utilizando el método de extensión desde Cast Enumerable:

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

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

Utilice un carácter comodín unido:

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

Utilice el método Cast extensión desde IEnumerable.

0

No se puede getListA1() y getListA2() solo devuelve Tipos de lista en la primera instancia?

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

pensé en esto antes. El problema es que estos 2 métodos se utilizan en otro lugar, y he cambiado todo el lugar relacionado. – 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

¡Gracias! Solo te di un voto. – zsong

0

probar este ejemplo:



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

Cuestiones relacionadas