开发者

Design pattern: Polymorphism for list of objects

开发者 https://www.devze.com 2022-12-28 15:49 出处:网络
Suppose I have a class A, and A1, A2 inherits from A. There are 2 functions: List<A1> getListA1(){...}

Suppose I have a class A, and A1, A2 inherits from A. There are 2 functions:

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

Now I want to do something similar to both A1 and A2 in another function

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

If I want to pass the instance of either ListA1 or ListA2, of course the types doesn't match because the compiler doesn't allow the coercion from List< A1> to List< A>. I can't do something like this:

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

So what is the best approach to the process()? Is there any way to do it in a universal way 开发者_JAVA百科rather than write the similar code to both List and List?


While I can't offer a java solution, here are some for C# ...

If you can alter the signature of Process to accept IEnumerable ...

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

then, in C# 4.0, everything will just work, thanks to the improved support for co- and contra-variance.

If you're working in C# 3.0, you can introduce a generic type parameter to the method:

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

Then, you can call passing either List or List and the generic type parameter will bind accordingly. Note that you don't often have to specify it directly, as type inferrence will usually give you what you need.

If this doesn't suit, you could convert the List using the Cast extension method from Enumerable:

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

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


Use a wildcard bound:

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


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

}


Use the Cast extension method from IEnumerable.


Can't getListA1() and getListA2() just return List types in the first instance?

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


Try this example:



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

0

精彩评论

暂无评论...
验证码 换一张
取 消