ResutBuilder 学习笔记二:增加新的输入数据类型
我们在前面的博客中创建了一个非常简单的结果构建器ConcatBuilder
,用于连接多个字符串。 ConcatBuilder
虽然非常简单,但已经展现出一些令人兴奋的特征,代码简洁,清晰,但是还远远不够。这篇博文讨论如何为ConcatBuilder
增加新的数据类型。
增加整数输入类型
假设我们需要使用ConcatBuilder
将一些整数进行连接,并且按下述方式输入整数:
@ConcatBuilder var str:String { "春眠不觉晓""处处闻啼鸟"123}
很遗憾,编译器会报错,因为ConcatBuilder
现在不理解整数。我们需要在ConcatBuilder
中像下面这样实现buildExpression
函数。
static func buildExpression (_ component: Int) -> String {return "\(component)" }
实现上述函数后,所有的组件输入首先要通过该函数进行转换,因而原先的字符串组件的输入会出错。修正这个错误很容易,我们只需要像下面这样增加一个新buildExpression
函数即可:
static func buildExpression (_ component: String) -> String {return component }
有了这两个函数,再次运行,这次结果正确。
@ConcatBuilder var str:String { "春眠不觉晓""处处闻啼鸟"123}print( str ) //春眠不觉晓处处闻啼鸟123
增加自定义输入类型
从上面我们可以看到,在结果构建器中,增加对整数类型的支持非常容易。类似地,增加对其他Swift数据类型的支持也不难,只需要重载buildExpression
函数即可。你也许觉得太容易了,不以为然。实际上,buildExpression
函数强大之处是可以非常容易增加自定义的输入数据类型,从而创建特定于场景的简单清晰表达。
比如在字符串拼接时经常会将一组连续的符号*
拼接,我们什么都不做,像下面这样就可以:
@ConcatBuilder var str:String { "*****""春眠不觉晓""处处闻啼鸟""*****"}
但是,对于这个特定的场景,一组连续的*
,上述表达比较原始,既不简洁,也容易出错。 如果能够像下面这样,既简洁、清晰,又不容易出错,不是更好吗?
@ConcatBuilder var str:String { Star(length:5) "春眠不觉晓""处处闻啼鸟"Star(length:5) }
这次,我们要做的就增加新的数据类型Star
,然后在ConcatBuilder
中增加相应的buildExpression
函数,以增加对Star的支持,后者和增加对整数的支持一样的简单。
首先增加数据类型Star
,如下
struct Star {let length:Intfunc getString()->String{return Array(repeating:"*",count:length).joined()}
}
其次,在ConcatBuilder
中增加如下buildExpression
函数:
static func buildExpression (_ component: Star) -> String {return component.getString() }
看看最后的结果:
@ConcatBuilder var str:String { Star(length:5)"春眠不觉晓""处处闻啼鸟"Star(length:5)}print( str )//*****春眠不觉晓处处闻啼鸟*****
是不是很酷呢?
小结
本文介绍了如何使用buildExpression
函数在结果构建器中增加对新的输入数据类型的支持, 特别是对自定义数据类型的支持。后者非常重要,它是实现一个DSL(领域特定语言)的基础。