2010-04-28 110 views
7
列表

假设我有一个A类,并且A1,A2从A 继承有两种功能:设计模式:多态的对象

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

现在我想做类似于A1两者的东西, A2在另一个函数

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

如果我想通过其中ListA1或ListA2的情况下,当然类型不匹配,因为编译器不允许从列表< A1胁迫>列出<一个>。我不能这样做:

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

那么什么是过程()的最佳方法?有没有办法以通用的方式来完成它,而不是将相似的代码写入List和List?

回答

8

虽然我不能提供一个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 { ... } 

然后,你可以调用传递任何列表或列表和泛型类型参数将相应绑定。请注意,您通常不需要直接指定它,因为类型推理通常会为您提供所需的内容。

如果不适合,你可以使用Cast扩展方法从可枚举转换列表:

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

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

使用结合一个通配符:

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

使用自IEnumerable的Cast扩展方法。

0

不能getListA1()getListA2()只是返回第一个实例中的列表类型?

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

我才想到这个问题。问题是这两个方法在其他地方使用,我已经改变了所有相关的地方。 – zsong 2010-04-28 03:54:07

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

谢谢!刚刚给了你一票。 – zsong 2010-04-28 04:07:08

0

试试这个例子:



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