【问题标题】:Java overload: how to call more specific oneJava重载:如何调用更具体的一个
【发布时间】:2020-04-07 18:01:05
【问题描述】:

我的程序解析WebAssembly 指令并根据当前指令的上下文做出决定。因此,我的算法的 MWE 如下所示:

public class Main {
    public interface Context {
        String name();
    }
    static class M implements Context {
        public String name() {
            return "Context M: ";
        }
    }
    static class N implements Context {
        public String name() {
            return "Context N: ";
        }
    }

    public interface Instruction {
        int getId();

        String run();
    }

    static class A implements Instruction {
        public int getId() {
            return 0;
        }

        public String run() {
            return "The work of A";
        }
    }

    static class B implements Instruction {
        public int getId() {
            return 1;
        }

        public String run() {
            return "The work of B";
        }
    }

    static void work(Context context, Instruction instruction) {
        switch (instruction.getId()) {
            case 0:
                workOnId0(context, (A) instruction);
                break;
            case 1:
                workOnId1(context, (B) instruction);
                break;
            default:
                throw new RuntimeException("Failed to recognize instruction");
        }
    }

    static void workOnId0(Context context, A instruction) {
        System.out.println(context.name() + instruction.run());
    }

    static void workOnId1(Context context, B instruction) {
        System.out.println(context.name() + instruction.run());
    }

    static void workOnId1(N context, B instruction) {
        System.out.println("This is corner case logic for this context!");
    }

    public static void main(String[] args) {
        N context = new N();
        B instruction = new B();

        work(context, instruction);
    }
}

从上面可以看出,当我的指令是B时,那么普通的工作应该发生在workOnId1,但是如果我的上下文具体是N,我希望做一些特殊的工作,即由 workOnId1 的不同重载表示。

不幸的是,特殊的重载永远不会被调用。如何使重载解决方案起作用?

【问题讨论】:

  • 是和不是。该问题表明,由于work 的参数是Context 类型,因此将始终选择workOnId1(Context, whatever)。但是,我目前不知道如何解决这个问题
  • 我想知道使用泛型是否可行? static void <T implements Context> work(T context, Instruction instruction)
  • 我认为泛型不会有帮助,因为在运行时所有这些类型都是Object,所以编译器无法区分这些方法
  • 这里是否可以选择多态性(例如,将 workOnId1 放入 Context 中)?
  • @Jaybird 我不这么认为。要完成的工作类型取决于对(上下文,指令),所以如果我将所有内容都推入上下文,这意味着每个上下文都必须了解每条指令?

标签: java overload-resolution


【解决方案1】:

workOnId1(Context context, B instruction) 将始终被调用,因为您有一个 Context 对象。

您需要通过转换为N 来区分方法调用。如果这在您的模型中效果不佳,因为我猜这只是一个小例子,您可能需要重新考虑您的整体设计。一个简单的解决方案是:

if(context instanceof N) {
   workOnId1((N)context, (B)instruction);
} else {
   workOnId1(context, (B) instruction);
}

【讨论】:

    【解决方案2】:

    you can change one line under case:1 as below to achieve your target

    switch (instruction.getId()) {
                case 0:
                    workOnId0(context, (A) instruction);
                    break;
                case 1:
                    workOnId1((context instanceof N)? (N)context :context, (B) instruction);                break;
                default:
                    throw new RuntimeException("Failed to recognize instruction");
            }
    

    【讨论】:

    • 三元表达式的结果将是 Context 类型的——我认为这行不通
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-17
    • 2016-05-12
    • 1970-01-01
    • 2016-08-27
    • 2014-01-26
    • 1970-01-01
    相关资源
    最近更新 更多