ITmob-Ly
发布于 2022-10-28 / 287 阅读
0

Kotlin中的尾缀 Lambda(Trailing Lambda)和尾随逗号(Trailing Comma)

两者一起介绍并不是它们有多少联系,单单只是因为一个叫 Trailing Lambda 一个叫 Trailing Comma,名字相似而已。

尾缀 Lambda(Trailing Lambda)

如果函数的最后一个参数是一个函数, 如果使用 Lambda 表达式作为这个参数的值, 可以将 Lambda 表达式写在函数调用的括号之外。

var result = operateValues(x, y) { input1, input2 ->
    input1 + input2
}

// 如果 Lambda 表达式是函数调用时的唯一参数, 括号可以完全省略:
var result = operateValues { input1, input2 ->
    input1 + input2
}

尾缀 lambda 好像是 Kotlin 中独特的新事物,我所了解的其他几个常用语言没有遇到过类似语法。Lambda表达式在括号之外,看起来像一个函数实现。最初使用时总不习惯这种语法,要提醒自己它是最后一个参数。

尾随逗号(Trailing Comma)

尾随逗号是指, 在一系列元素的最末尾之后出现的逗号:

class Person(
    val firstName: String,
    val lastName: String,
    val age: Int, // 尾随逗号
)

尾随逗号是可选的。Kotlin 编码风格鼓励在声明处使用尾随逗号。

使用尾随逗号的益处:

  • 版本控制中的差分比较更加清晰 – (因为差分只会出现在真正修改过的代码行)
  • 更加易于添加元素, 或改变元素顺序 – (修改元素时不再需要添加或删除逗号)
  • 简化了代码生成工作, 比如, 对于对象的初始化代码. 最后一个元素也可以带有逗号.

如下是文档中尾随都会在各种情况下使用的示例:

枚举

enumclass Direction {
    NORTH,
    SOUTH,
    WEST,
    EAST, // 尾随逗号
}

值参数

fun shift(x: Int, y: Int) { /*...*/ }
shift(
    25,
    20, // 尾随逗号
)
val colors = listOf(
    "red",
    "green",
    "blue", // 尾随逗号
)

类的属性和参数

class Customer(
val name: String,
val lastName: String, // 尾随逗号
)
class Customer(
val name: String,
    lastName: String, // 尾随逗号
)

函数值参数

fun powerOf(
    number: Int,
    exponent: Int, // 尾随逗号
) { /*...*/ }
constructor(
    x: Comparable<Number>,
    y: Iterable<Number>, // 尾随逗号
) {}
fun print(
vararg quantity: Int,
    description: String, // 尾随逗号
) {}

带有可选类型的参数 (包括属性的 set 函数)

val sum: (Int, Int, Int) -> Int =fun(
    x,
    y,
    z, // 尾随逗号
): Int {
return x + y + x
}
println(sum(8, 8, 8))

下标后缀

class Surface {
operatorfunget(x: Int, y: Int) = 2 * x + 4 * y - 10
}
fun getZValue(mySurface: Surface, xValue: Int, yValue: Int) =
    mySurface[
        xValue,
        yValue, // 尾随逗号
    ]

Lambda 表达式的参数

fun main() {
val x = {
            x: Comparable<Number>,
            y: Iterable<Number>, // 尾随逗号
        ->
        println("1")
    }
    println(x)
}

when 语句的分支条件

fun isReferenceApplicable(myReference: KClass<*>) =when (myReference) {
    Comparable::class,
    Iterable::class,
    String::class, // 尾随逗号
        ->trueelse ->false
}

集合字面值 (在注解中)

annotationclass ApplicableFor(val services: Array<String>)
@ApplicableFor([
    "serializer",
    "balancer",
    "database",
    "inMemoryCache", // 尾随逗号
])
fun run() {}

类型参数(Type argument)

fun <T1, T2> foo() {}

fun main() {
    foo<
            Comparable<Number>,
            Iterable<Number>, // 尾随逗号
            >()
}

类型参数(Type parameter)

class MyMap<
        MyKey,
        MyValue, // 尾随逗号
        > {}

解构声明

dataclass Car(val manufacturer: String,val model: String,val year: Int)
val myCar = Car("Tesla", "Y", 2019)
val (
    manufacturer,
    model,
    year, // 尾随逗号
) = myCar
val cars = listOf<Car>()
fun printMeanValue() {
var meanValue: Int = 0
for ((
        _,
        _,
        year, // 尾随逗号
    )in cars) {
        meanValue += year
    }
    println(meanValue/cars.size)
}
printMeanValue()