java和scala代码 scala和java混编( 六 )


换句话说 (最终的)目标是要允许客户机编写代码 以达到如下的目的
清单 计算器 DSL 目标
// This is Java using the Calculator String s = (( * ) + ) ; double result = tedneward calcdsl Calculator evaluate(s); System out println( We got + result); // Should be
我们不会在一篇文章完成所有的论述 但是我们在本篇文章中可以学习到一部分内容 在下一篇文章完成全部内容
从实现和设计的角度看 可以从构建一个基于字符串的解析器来着手构建某种可以 挑选每个字符并动态计算 的解析器 这的确极具诱惑力 但是这只适用于较简单的语言 而且其扩展性不是很好 如果语言的目标是实现简单的扩展性 那么在深入研究实现之前 让我们先花点时间想一想如何设计语言
根据那些基本的编译理论中最精华的部分 您可以得知一个语言处理器(包括解释器和编译器)的基本运算至少由两个阶段组成
●解析器 用于获取输入的文本并将其转换成 Abstract Syntax Tree(AST)●代码生成器(在编译器的情况下) 用于获取 AST 并从中生成所需字节码 或是求值器(在解释器的情况下) 用于获取 AST 并计算它在 AST 里面所发现的内容
拥有 AST 就能够在某种程度上优化结果树 如果意识到这一点的话 那么上述区别的原因就变得更加显而易见了 对于计算器 我们可能要仔细检查表达式 找出可以截去表达式的整个片段的位置 诸如在乘法表达式中运算数为 的位置(它表明无论其他运算数是多少 运算结果都会是 )
您要做的第一件事是为计算器语言定义该 AST 幸运的是 Scala 有 case 类 一种提供了丰富数据 使用了非常薄的封装的类 它们所具有的一些特性使它们很适合构建 AST
case 类
在深入到 AST 定义之前 让我先简要概述一下什么是 case 类 case 类是使 scala 程序员得以使用某些假设的默认值来创建一个类的一种便捷机制 例如 当编写如下内容时
清单 对 person 使用 case 类
case class Person(first:String last:String age:Int){}
Scala 编译器不仅仅可以按照我们对它的期望生成预期的构造函数 — Scala 编译器还可以生成常规意义上的 equals() toString() 和 hashCode() 实现 事实上 这种 case 类很普通(即它没有其他的成员) 因此 case 类声明后面的大括号的内容是可选的
清单 世界上最短的类清单
case class Person(first:String last:String age:Int)
这一点通过我们的老朋友 javap 很容易得以验证
【java和scala代码 scala和java混编】清单 神圣的代码生成器 Batman!
C:\Projects\Exploration\Scalajavap PersonCompiled from case scala public class Person extends java lang Object implements scala ScalaObject scala Product java io Serializable{public Person(java lang String java lang String int);public java lang Object productElement(int);public int productArity();public java lang String productPrefix();public boolean equals(java lang Object);public java lang String toString();public int hashCode();public int $tag();public int age();public java lang String last();public java lang String first();}
如您所见 伴随 case 类发生了很多传统类通常不会引发的事情 这是因为 case 类是要与 Scala 的模式匹配(在 集合类型 中曾简短分析过)结合使用的
使用 case 类与使用传统类有些不同 这是因为通常它们都不是通过传统的 new 语法构造而成的 事实上 它们通常是通过一种名称与类相同的工厂方法来创建的
清单 没有使用 new 语法?
object App{def main(args : Array[String]) : Unit ={val ted = Person( Ted Neward )}}
case 类本身可能并不比传统类有趣 或者有多么的与众不同 但是在使用它们时会有一个很重要的差别 与引用等式相比 case 类生成的代码更喜欢按位(biise)等式 因此下面的代码对 Java 程序员来说有些有趣的惊喜

推荐阅读