设计模式:对象列表的多态性

时间:2010-04-28 03:46:40

标签: c# java design-patterns

假设我有一个A类,A1,A2继承自A. 有两个功能:

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

现在我想在另一个函数

中做类似于A1和A2的事情
public void process(List<A>){...}

如果我想传递ListA1或ListA2的实例,当然类型不匹配,因为编译器不允许来自List&lt;的强制。 A1&GT;列出&lt; a取代。我做不到这样的事情:

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

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

6 个答案:

答案 0 :(得分:8)

虽然我不能提供java解决方案,但这里有一些用于C#...

如果你可以改变Process的签名来接受IEnumerable ......

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

然后,在C#4.0中,由于对共同和反差的改进支持,一切都会正常工作。

如果您使用的是C#3.0,则可以在方法中引入泛型类型参数:

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

然后,您可以调用传递List或List,并且泛型类型参数将相应地绑定。请注意,您通常不必直接指定它,因为类型推断通常会为您提供所需的内容。

如果这不合适,您可以使用Enumerable中的Cast扩展名转换List:

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

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

答案 1 :(得分:6)

使用通配符绑定:

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

答案 2 :(得分: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);
    }

}

答案 3 :(得分:0)

使用IEnumerable中的Cast扩展名方法。

答案 4 :(得分:0)

getListA1()getListA2()只能在第一个实例中返回List类型吗?

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

答案 5 :(得分: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
    }
}