微信 订阅号助手 的Android App项目首次尝试使用Kotlin进行大规模的业务开发(483个Kt文件,3.8W行不包含空行的Kt代码),一开始接触Kotlin的时候难免会有点不适应,但经过几天的强制使用后,慢慢有些感觉,项目落地后回顾了一下,发现Kotlin确实是有它独特的风味
色香味倶全,敬请尽情享受这番独特的风味
食用安全,Nullable or NotNul从源头抓起,Kotlin代码安全性更强
var output: String
output = null // Compilation error
val name: String? = null // Nullable type
println(name.length()) // Compilation error
食用安全从从源头上抓起,只要跟定义不符就编译不通过,这是Kotlin小而精的一个优点,一下子能把整碟"菜"的安全系数提高,此Code来自官方文档
项目工具类的另一种写法
fun String.toIntSafely(defaultValue: Int = 0): Int {
return try {
this.toInt()
} catch (e: Exception) {
defaultValue
}
}
fun main(args: Array<String>) {
println("1".toIntSafely())
}
String 转 Int,这种需求几乎很多项目都是需要,像上述Kotlin如果是在Java里面描述的话,估计会写成这样
public final class StringUtil{
private StringUtil() {}
public static int stringToInt(String string, int defaultValue) {
//省略
}
}
使用时
StringUtil.stringToInt("1", 0);
大家看到这里可能会觉得没什么,大家都是工具类,用的时候有些小差别而已
但正因为这些小差别,优点就体现出来了,确实是鲜美
虽然这个概念在面向对象领域用得很多,但Kotlin这个重载的味道真是令我们吃上瘾
重载在工具类的场景用得非常多,一个项目下来没工具类也是不可能,例如我们在项目中会封装一些对话框(Dialog)工具类供开发的同学一句调用
这些场景估计做Android开发的同学都会碰到,其实不限于Android,Java开发的同学也经常遇到,我们看看Kotlin是怎样把这些需求收拢
fun showDialog(title: String = "标题", message: String = "内容") {
//TODO
}
这个写法一下子满足 2的2次方(4) 种重载方法
showDialog()
showDialog("新标题")
showDialog(message = "新内容")
showDialog("新标题", "新内容")
这种重载方式有效地减少我们项目中的重载方法数量,使得我们项目开发更简洁和更有效率 ,自然就回味无穷
Kotlin里面Function与Lambda既可相互理解,又有其味道(写法)上的一些差异
Function(函数)常用写法
fun f(x: Int): Any {
return Any()
}
用法
val y = f(1)
Function(函数)的一种Lambda写法
fun f() = { x: Int -> Any() } 等价于 fun f(): (Int) -> Any = { x: Int -> Any() }
用法
val y = f()(1) 或 val y = f().invoke(1)
Lambda写法
val f = { x: Int -> Any() } 等价于 val f: (Int) -> Any = { x: Int -> Any }
用法
val y = f(1) 或 val y = f.invoke(1)
细节点:Function时,有"="跟没有"="意义不一样,有"="的时候可以理解右边( { x: Int -> Any() } )是 左边函数返回类型((Int) -> Any) 的实现
函数不用置疑,项目里面必备
Lambda,语法糖,这是怎样的一种成份?
Lambda是长这样的
val block: () -> Unit = {}
val sum: (Int, Int) -> Int = { p1, p2 -> p1 + p2 }
Lambda令我们的项目减少了很多接口类,尤其是回调接口,我们项目几乎没有。一般的业务场景里面回调接口都会用得不少,Lambda能有效减少这种Callback接口的定义,少写不少接口类,事半功倍。
另lambda里面不能写return,最后一行的值就是返回值
从数学函数角度抽象理解
函数: y = f(x)
假设x与y都是Int类型
可以理解为 Kotlin 函数:
fun f(x: Int): Int {
return 1 // 这里的返回值就是对应y
}
也可以理解为 Lambda:
val f = { x: Int -> 1 } 等价于 val f: (Int) -> Int = { x: Int -> 1 }
使用时f(1),但是如果像上述那种f(x)的kotlin函数与f(x)的lambda同时同名同方法签名存在,使用上要f(1)与f.invoke(1)来区分是函数调用还是lambda调用
假设x与y都是Lambda类型
x是Lambda类型 (Int) -> Int ,y是Lambda类型 (Int) -> Int,可以换算成
fun f(x: (Int) -> Int): (Int) -> Int {
return { it -> x(it) }
}
或这样
fun f(x: (Int) -> Int): (Int) -> Int = { it -> x(it) }
使用时
f { it -> it + 10 }(1) or f { it -> it + 10 }.invoke(1)
或 Lambda
val f: ((Int) -> Int) -> ((Int) -> Int) = { x -> { it -> x(it) } } // val时要inline
使用时
f.invoke { it -> it + 10 }.invoke(1)
通过上述的 替换 能更好地理解和使用Lambda
希望Kotlin这款食材能带给各位读者不少Android上的特色的风味
https://kotlinlang.org