2010-04-28 109 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 
    } 
}