kotlin小知识系列1-dsl和invoke约定
kotlin小知识系列是连载文,会不定期的进行更新
invoke约定
kotlin中,为了更加方便的支持dsl,提供了一个特殊的函数,invoke约定函数。看下代码说明它的作用。
class Dependencies {
fun compile(str: String) {
println("compile $str")
}
fun annotationProcessor(str: String) {
println("annotationProcessor $str")
}
operator fun invoke(block: Dependencies.() -> Unit) {
block()
}
}
fun main(args: Array<String>) {
val dependencies=Dependencies()
dependencies {
compile("com.android.support:support-v4:23.1.1")
annotationProcessor("com.jakewharton:butterknife-compiler:8.4.0")
}
//上面的调用方式相当于下面
dependencies.compile(“com.android.support:support-v4:23.1.1”)
dependencies.annotationProcessor("com.jakewharton:butterknife-compiler:8.4.0")
}
通过代码可以看出invoke约定函数,就是为对象提供了一个直接调用方法的途径。当然了,除了上述类似dsl的调用途径外,invoke本身也是个普通方法。也可以对其进行参数设置。例如:
class DownloadManager {
fun download(url: String) {
println("downManager down $url ")
}
operator fun invoke(url: String) {
println("invoke $url ")
download(url)
}
}
val downloadManager = DownloadManager()
//正常调用方法
downloadManager.download("www.demon-yu.com/file")
//高级调用方法
downloadManager("www.demon-yu.com/file1")
downloadManager("www.demon-yu.com/file2")
downloadManager("www.demon-yu.com/file3")
两个例子可是说是比较常用的例子了~
dsl领域专用语言
kotlin本身语言的特性,天生支持dsl。主要用涉及扩展函数、lambda、中缀调用、invoke 约定和函数小括号省略等几个特性。 android的编译环境gradle就是典型的dsl的应用。只是目前gradle使用的是grovvy语言,下面我用kotlin实现一个说明的例子。
class Gradle {
//采用成员变量进行dsl
val dependencies = Dependencies()
//采用函数dsl,Android不包含invoke函数
private val _android = Android()
fun android(block: Android.() -> Unit) {
_android.block()
}
//invoke约束杉树
operator fun invoke(block: Gradle.() -> Unit) {
block()
}
}
//android对象配置
class Android {
//两种方式
var compileSdkVersion = -1
fun compileSdkVersion(sdk: Int) {
compileSdkVersion = sdk
}
//直接赋值
var targetSdkVersion = 12
//defaultConfig对象配置
val defaultConfig = DefaultConfig()
}
//android 默认config
class DefaultConfig {
//设置applicationId
var applicationId = ""
get() {
println("get applicationId")
return field
}
set(value) {
println("set applicationId")
field = value
}
operator fun invoke(block: DefaultConfig.() -> Unit) {
block()
}
}
//依赖管理对象
class Dependencies {
//编译依赖
fun compile(str: String) {
println("compile $str")
}
//竹节处理器
fun annotationProcessor(str: String) {
println("annotationProcessor $str")
}
operator fun invoke(block: Dependencies.() -> Unit) {
block()
}
}
fun main(args: Array<String>) {
var gradle = Gradle()
gradle {
android {
compileSdkVersion(2)
compileSdkVersion = 2
targetSdkVersion = 27
defaultConfig {
applicationId = "com.google.android.internal"
}
}
dependencies {
compile("com.android.support:support-v4:23.1.1")
annotationProcessor("com.jakewharton:butterknife-compiler:8.4.0")
}
}
}
下面,我着重分析下几个要点
kotlin的lamada表达式
...
class Dependencies {
//编译依赖
fun compile(str: String) {
println("compile $str")
}
//竹节处理器
fun annotationProcessor(str: String) {
println("annotationProcessor $str")
}
operator fun invoke(block: Dependencies.() -> Unit) {
block()
}
}
...
dependencies {
compile("com.android.support:support-v4:23.1.1")
annotationProcessor("com.jakewharton:butterknife-compiler:8.4.0")
}
...
Dependencies 的约定invoke函数的参数是一个带有接收者的lambda表达式,同时由于invoke函数唯一参数是个lambda表达式,可以省略小括号。 所谓带有接收者的lambda表达式,我觉得更像一个闭包环境,而环境的context就是lambda的调用者,如果没有显示的指明调用者的话,就是当前的对象this了。
再看一个显示指明lambda调用者的情况
class Theme {
var icon: String? = null
var color: String? = null
override fun toString(): String {
return "$icon $color"
}
}
fun global(block: Theme.() -> Unit): Theme {
val theme = Theme()
theme.block()
return theme
}
fun main(args:Array<String>){
val theme = global {
icon = "柯南皮肤"
color = "蓝色"
}
println(theme)
}
代码很简单,就不仔细说明了~~
本文由 陌路风尘 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为:
2018/08/21 18:04