Задача о двойной отправке с фиксированным классом - PullRequest
2 голосов
/ 26 сентября 2011

У меня есть 3 класса: ** родитель **, ** ребенок1 ** и ** ребенок2 **. И Child1, и Child 2 расширяют Parent, и их ** нельзя ** изменить.

Существует класс Action, определенный следующим образом:

public class Action {
    public static void perform(Parent p) {
        if (p instanceof Child1) {
            action((Child1)p);
        }
        else if (p instanceof Child2) {
            action((Child2)p);
        }
        else {
            action(p);
        }
    }

    private static void action(Parent p) {
        ...
    }
    private static void action(Child1 c1) {
        ...
    }
    private static void action(Child2 c2) {
        ...
    }
}


Parent p = new Child1();
Action.perform(p);

Без instanceof , есть ли способ получить то же поведение, что и выше?

======
(Модифицированный)

PS: данный тип аргумента Action.perform - Parent, но его значение - Child1, поэтому я думаю, что перегрузка метода не работает ....

Ответы [ 2 ]

0 голосов
/ 26 сентября 2011

Вот два решения C #, одно из них в основном то же самое, но более аккуратное и хорошо, когда у вас небольшое количество дочерних классов.

public class Parent
{
}

public class Child1 : Parent
{
}

public class Child2 : Parent
{
}

public class Action
{
    private static Dictionary<Type, Action<Parent>> _d = new Dictionary<Type, Action<Parent>>()
                                                    {
                                                        {typeof(Child1), p=>action((Child1)p)},
                                                        {typeof(Child2), p=>action((Child2)p)},
                                                        {typeof(Parent), p=>action(p)}
                                                    };
    public static void perform(Parent p)
    {
        _d[p.GetType()](p);
    }

    private static void action(Parent p)
    {

    }

    private static void action(Child1 c1)
    {

    }
    private static void action(Child2 c2)
    {

    }
}



class Program
{
    static void Main(string[] args)
    {
        Parent p = new Child1();
        Action.perform(p);
    }
}`enter code here`

В любом случае, это нарушает OCP, но быстрее, чем использование отражения.Этот не нарушает OCP, но использует отражение для заполнения словаря:

public class Action
        {
            private static Dictionary<Type, Action<Parent>> _d;

            static Action()
            {
                Initialize();
            }

            private static void Initialize()
            {
                var methods = typeof(Action)
                    .GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
                    .Where(IsActionMethod)
                    .ToList();

                _d = methods.ToDictionary(m => m.GetParameters().First().ParameterType,
                                          m => (Action<Parent>) (x => m.Invoke(null, new[] {x})));
            }

            private static bool IsActionMethod(MethodInfo methodInfo)
            {
                var parameters = methodInfo.GetParameters();

                return parameters.Length == 1
                       && typeof(Parent).IsAssignableFrom(parameters.First().ParameterType)
                       && methodInfo.ReturnType == typeof(void);
            }

            public static void perform(Parent p)
            {
                _d[p.GetType()](p);
            }

            private static void action(Parent p)
            {

            }

            private static void action(Child1 c1)
            {

            }

            private static void action(Child2 c2)
            {

            }
}
0 голосов
/ 26 сентября 2011

К сожалению, я думаю, что вам придется прибегнуть к размышлениям, чтобы решить эту проблему.

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