我有一个开关语句,它将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),例如:
nameToOperation.put("+", new Operation("+", 1, Driver.class.getMethod("add")));
nameToOperation.put("car", new Operation("car", 1, Driver.class.getMethod("car")));
因此,Operation类将有N个不同的实例,每个实例都包含字符串、方法和参数数量
然后,我可以简单地使用类似的方法调用该方法(我知道这不是使用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()));
然而,我仍然不完全喜欢这个解决方案,因为我正在失去类型html" target="_blank">安全性,它看起来仍然不太好。我在stackoverflow上看到的另一个例子看起来很优雅,但我不完全理解,这是上面答案的第一个解决方案:如何调用存储在HashMap中的方法?(Java)
Stackoverflow上的每个人都认为最好的解决方案是什么?
编辑:为了防止有人搜索到这个,并对我的解决方案感到疑惑,我让每个操作(如Add、Car、Cdr)都有自己的类来实现命令。然后,我不得不使我的大多数方法都是静态的,我想它们本质上都是静态的。这似乎比最初的案例陈述要优雅得多。
看起来您正在尝试编写Scheme解释器。在这种情况下,您无论如何都需要一个映射,因为您需要存储所有用户定义的值和函数。当用户写入例如(define(add a b)(a b))时,您使用“add”作为键将函数存储在映射中。但是您的函数应该使用列表作为输入,即每个函数只有一个参数,即列表。在Scheme中,所有表达式都是列表。通常,方案解释器由一个读取器和一个求值器组成。读取器将代码转换为一组嵌套列表。因此,基本上“(define(addab)(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);
当然,您的代码实际上不是这样的,而是通过递归方法解析输入代码来构建列表。
顺便说一句,这些列表不仅包含字符串,还包含数字和布尔值。像这样的嵌套列表是抽象语法树(AST)最简单的形式。由于Scheme的语法比大多数其他语言简单得多,因此一个非常简单的列表结构就足以存储解析后的代码。
然后,评估者处理这些列表。要计算列表,首先递归计算列表中的每个元素,然后将第一个元素应用于列表的其余部分。因此,第一个元素必须是用户定义的函数或内置命令,例如“define”。
基本上,答案建议使用命令模式。
"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"
switch 语句可以替代多个 if 判断。 switch 语句为多分支选择的情况提供了一个更具描述性的方式。 语法 switch 语句有至少一个 case 代码块和一个可选的 default 代码块。 就像这样: switch(x) { case 'value1': // if (x === 'value1') ... [break] case 'value2':
使用 switch 语句可以更简洁地实现 if ~ else if 的结构。格式如下。 switch(base_expression) { casecondition_expression1: casecondition_expression2: : : default: : : } 写在 base_expression 位置的表达式会在刚开始时被求值。switch 后面的语句块中的 case
C# 中的 switch 语句有些类似于《 if else if 语句》,都可以根据表达式执行某个的语句块,其语法格式如下: switch(表达式){ case value1: //表达式的值为 value1 时,要执行的代码 break; case value2: //表达式的值为 value2 时,要执行的代码 break;
当条件判断分支太多的时候,我们会使用switch语句来优化逻辑。 package main import "fmt" import "time" func main() { // 基础的switch用法 i := 2 fmt.Print("write ", i, " as ") switch i { case 1: fmt.Println("
Swift 条件语句 switch 语句允许测试一个变量等于多个值时的情况。 Swift 语言中只要匹配到 case 语句,则整个 switch 语句执行完成。 语法 Swift 语言中 switch 语句的语法: switch expression { case expression1 : statement(s) fallthrough /* 可选 */
switch 语句评估一个表达式,将表达式的值与case子句匹配,并执行与该情况相关联的语句。—— MDN switch 是另一种控制流程的方式,根据条件执行不同的代码块。 能用 switch 实现的都可以用 if 实现。 1. 基本语法 switch (表达式) { case 表达式结果为值1的时候: 做的事情; break; case 表达式结果为值