繁体   English   中英

切换语句或远程调用方法

[英]Switch statement or remotely invoke methods

我有一个switch语句,将一个String与一组String相比较,其中每个匹配项调用一个不同的方法。

switch(((Operation) expr.getData()).getValue()){
        case "+":
            return add(expr.getNext());
        case "car":
            return car(expr.getNext());
        case "cdr":
            return cdr(expr.getNext());
        case "cons":
            return cons(expr.getNext(), expr.getNext().getNext());
        case "quote":
            return quote(expr.getNext());
        case "define":
            handleDefine(expr.getNext());
            break;
        default:
            return null;
        }

但是,对我来说,这听起来像是可以通过使用HashMap来更优雅,更有效地实现的,该HashMap链接到包含一个Method和参数数量的Operation ,因此我可以将每个方法都转换为HashMap例如:

nameToOperation.put("+", new Operation("+", 1, Driver.class.getMethod("add")));
nameToOperation.put("car", new Operation("car", 1, Driver.class.getMethod("car")));

因此,将有N个不同的Operation类实例,每个实例包含String,Method和参数数量

然后,我可以使用与此类似的东西简单地调用该方法(我知道这不是您使用invoke的方式):

Operation op = ((Operation) expr.getData())

if(op.getNumPars() == 1)
    return(op.getMethod().invoke(expr.getNext()));
else
    return(op.getMethod().invoke(expr.getNext(), expr.getNext().getNext()));

但是,我仍然不完全喜欢这种解决方案,因为我失去了类型安全性,而且看起来还不太好。 我在stackoverflow上看到的另一个例子看起来很优雅,但是我不完全理解,这是有关以下内容的最佳答案的第一个解决方案: 如何调用存储在HashMap中的方法? (JAVA)

Stackoverflow上的每个人都认为最好的解决方案是什么?

编辑:以防万一有人搜索此文件并想知道我的解决方案,我让诸如Add,Car,Cdr之类的每个操作都有自己的实现Command的类。 然后,我不得不使我的大多数方法静态化,我自然认为每种方法都是静态的。 这似乎比原始的案例陈述更加优雅。

基本上,答案建议使用Command模式。

"The main advantage of the command design pattern is that it decouples the object that invokes the operation from the one that know how to perform it. And this advantage must be kept. There are implementations of this design pattern in which the invoker is aware of the concrete commands classes. This is wrong making the implementation more tightly coupled. The invoker should be aware only about the abstract command class"
  1. 基本上,您的地图将是类型安全的。 通过声明Map <character,Command>
  2. 开放可扩展

看来您正在尝试编写Scheme解释器。 在这种情况下,由于您需要存储所有用户定义的值和函数,因此无论如何都需要一个映射。 当用户编写例如(定义(添加ab)(+ ab))时,您可以使用“添加”作为键将功能存储在地图中。 但是您的函数应该使用列表作为输入,即每个函数只有一个参数,即一个列表。 在Scheme中,所有表达式都是列表。 通常,计划口译员由一名读者和一名评估员组成。 读者将代码转换为一堆嵌套列表。 因此,基本上“(define(add ab)(+ ab))”可以转换成与此类似的列表结构。

List<Object> list = new ArrayList<Object>();
List<Object> list2 = new ArrayList<Object>();
list2.add("add"); list2.add("a"); list2.add("b");
List<Object> list3 = new ArrayList<Object>();
list3.add("+"); list3.add("a"); list3.add("b");
list.add("define"); list.add(list1); list.add(list2);

当然,您的代码实际上并不像这样,而是通过解析输入代码的递归方法构造列表。

这些列表不仅包含字符串btw。,还包含数字和布尔值。 这样的嵌套列表是抽象语法树(AST)的最简单形式。 由于Scheme的语法比大多数其他语言的语法简单得多,因此非常简单的列表结构足以存储已解析的代码。

然后,评估者处理这些列表。 要评估列表,您首先要递归评估列表中的每个元素,然后将第一个元素应用于列表的其余部分。 因此,该第一个元素必须是用户定义的功能或内置命令,例如“ define”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM