Шаблон дизайна: Полиморфизм для списка объектов - PullRequest
7 голосов
/ 28 апреля 2010

Предположим, у меня есть класс A, и A1, A2 наследуется от A. Есть 2 функции:

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

Теперь я хочу сделать что-то похожее на A1 и A2 в другой функции

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

Если я хочу передать экземпляр ListA1 или ListA2, конечно, типы не совпадают, потому что компилятор не разрешает приведение из List в List . Я не могу сделать что-то вроде этого:

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

Так, каков наилучший подход к процессу ()? Есть ли способ сделать это универсальным способом, вместо того, чтобы писать похожий код в List и List?

Ответы [ 6 ]

8 голосов
/ 28 апреля 2010

Хотя я не могу предложить решение 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, и параметр универсального типа будет связываться соответствующим образом. Обратите внимание, что вам не нужно указывать его напрямую, так как вывод типа обычно даст вам то, что вам нужно.

Если это не подходит, вы можете преобразовать Список, используя метод расширения Cast из Enumerable:

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

var someList = getListA1();
Process( someList.Cast<A>());
6 голосов
/ 28 апреля 2010

Используйте подстановочный знак:

public void process(List<? extends A>){...}
1 голос
/ 28 апреля 2010
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 голосов
/ 28 апреля 2012

Попробуйте этот пример:



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 голосов
/ 28 апреля 2010

Не могут getListA1() и getListA2() просто вернуть типы списков в первом случае?

List<A> getListA1(){...}
List<A> getListA2(){...}
0 голосов
/ 28 апреля 2010

Используйте метод расширения Cast из IEnumerable.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...