代码运行输出结果如下:
网络异常,图片无法展示
|
使用场景
- 语言语法较为简单,且对执行效率要求不高时,如正则判断IP是否合法;
- 问题重复出现,且可用简单语法来进行表达时,如if-else统一解释为条件语句;
- 当一个语言需要解释执行时,如XML中<>括号标识不同的结点含义;
优点
- 易于实现语法,一条语法用一个解释器对象解释执行;
- 易于扩展新语法,只需创建对应解释器,抽象语法树时使用即可;
缺点
- 可使用场景少,复用性不高,除了发明新的编程语言或对某些新硬件进行解释外,很少用,特定数据结构,扩展性也低;
- 维护成本高,每种规则至少要定义一个解释类,语法规则越多,类越难管理和维护;
- 执行效率低,递归调用方法,解释句子语法复杂时,会执行大量循环语句;
0x3、加餐:Kotlin中创建一个自己的DSL示例
顺带提下Kotlin中的DSL,感兴趣的可以看看,用到了下面这些黑魔法:
扩展函数(属性) + lambda表达式 + 中缀表达式 + 运算符重载(invoke)
代码示例如下:
// 饭店 data class Restaurant(var name: String, var score: Int, var price: Int, var address: String) // 上下文类 data class Eating( var kind: String? = "", var area: String? = "", var restaurantList: List<Restaurant>? = mutableListOf() ) { override fun toString() = StringBuilder().apply { append("【${this@Eating.area}】的【${this@Eating.kind}】有下述门店:\n\n") this@Eating.restaurantList?.forEach { append("${it.name} - ${it.score}分 - ${it.price}元/人 - ${it.address}\n") } append("\n") }.toString() } class RestaurantBuilder { var name: String = "" var score: Int = 0 var price: Int = 0 var address: String = "" fun build(): Restaurant = Restaurant(name, score, price, address) } // 中间类,用于实现直接DSL方式添加Restaurant的效果 class EatingBuilder { var kind: String? = "" var area: String? = "" var restaurantList = mutableListOf<Restaurant>() fun restaurant(block: RestaurantBuilder.() -> Unit) { // 此处演示下invoke实现,可以直接restaurantList.add(RestaurantBuilder().apply(block).build()) val restaurantBuilder = RestaurantBuilder() block.invoke(restaurantBuilder) restaurantList.add(restaurantBuilder.build()) } fun build(): Eating = Eating(kind, area, restaurantList) } // 创建Eating的DSL写法(顶层函数) fun eating(block: EatingBuilder.() -> Unit): Eating = EatingBuilder().apply(block).build() // 此处为了演示使用中缀表达式,实际上可以直接赋值 infix fun Eating.area(area: String) { this.area = area } fun main() { val eating = eating { kind = "西式快餐" restaurant { name = "华莱士·全鸡汉堡" score = 5 price = 19 address = "观澜牛湖店" } restaurant { name = "汉堡王" score = 5 price = 33 address = "东海店" } restaurant { name = "麦当劳" score = 4 price = 34 address = "绒花路店" } } eating.area("平湖区") println(eating.toString()) }
代码运行输出结果如下:
网络异常,图片无法展示
|
以上就是本节课程的全部内容,谢谢~