关于固定类别的双重调度问题

发布于 2024-12-06 16:48:59 字数 813 浏览 3 评论 0原文

我有 3 个班级:**Parent**、**Child1** 和 **Child2**。 Child1 和 Child1 都子级 2 扩展了父级,并且它们**不能**修改。

有一个类 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,所以我认为方法重载不起作用......

I have 3 classes: **Parent**, **Child1**, and **Child2**. Both Child1 & Child 2 extend Parent and they **cannot** be modified.

There is a class Action defined as follows:

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

Without instanceof operator, is there any way to get the same behavior as above ?

======
(modified)

PS: the given argument type of Action.perform is Parent, but its value is Child1, so I think method overloading doesn't work ....

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

别闹i 2024-12-13 16:48:59

这里有两种 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)
            {

            }
}

Here are two C# solutions, one basically is the same but more neat and is good when you have small number of child classes.

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`

Anyhow it breaks OCP but is faster than using reflection. This one does not break OCP but uses reflection to fill the dictionary:

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)
            {

            }
}
我做我的改变 2024-12-13 16:48:59

不幸的是,我认为你必须诉诸反思来解决这个问题。

Unfortunately, I think you would have to resort to reflection to solve this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文