1 字符串内嵌表达式
首先来看一下Kotlin中字符串内嵌表达式的语法规则:
"hello, ${obj.name}. nice to meet you!"
可以看到,Kotlin允许我们在字符串里嵌入${}这种语法结构的表达式,并在运行时使用表达式执行的结果替代这一部分内容。
另外,当表达式中仅有一个变量的时候,还可以将两边的大括号省略,如下所示:
"hello, $name. nice to meet you!"
这种字符串内嵌表达式的写法到底有多么方便,我们通过一个具体的例子来学习一下就知道了。在前面,我们用Java编写了一个Cellphone数据类,其中toString()方法里就使用了比较复杂的拼接字符串的写法。这里我将当时的拼接逻辑单独提炼了出来,代码如下:
val brand = "Samsung"
val price = 1299.99
println("Cellphone(brand=" + brand + ", price=" + price + ")")
可以看到,上述字符串中一共使用了4个加号连接符,这种写法不仅写起来非常吃力,很容易写错,而且在代码可读性方面也很糟糕。
而使用字符串内嵌表达式的写法就变得非常简单了,如下所示:
val brand = "Samsung"
val price = 1299.99
println("Cellphone(brand=$brand, price=$price)")
很明显,这种写法不管是在易读性还是易写性方面都更胜一筹,是Kotlin更加推崇的写法。这个小技巧会给我们以后的开发工作带来巨大的便利。
2.8.2 函数的参数默认值
给参数设定默认值的方式也很简单,观察如下代码:
fun printParams(num: Int, str: String = "hello") {
println("num is $num , str is $str")
}
可以看到,这里我们给printParams()函数的第二个参数设定了一个默认值,这样当调用printParams()函数时,可以选择给第二个参数传值,也可以选择不传,在不传的情况下就会自动使用默认值。
现在我们在main()函数中调用一下printParams()函数来进行测试,代码如下:
fun printParams(num: Int, str: String = "hello") {
println("num is $num , str is $str")
}
fun main() {
printParams(123)
}
注意,这里并没有给第二个参数传值。运行一下代码,结果如图所示。
可以看到,在没有给第二个参数传值的情况下,printParams()函数自动使用了参数的默认值。
当然上面这个例子比较理想化,因为正好是给最后一个参数设定了默认值,现在我们将代码改成给第一个参数设定默认值,如下所示:
fun printParams(num: Int = 100, str: String) {
println("num is $num , str is $str")
}
这时如果想让num参数使用默认值该怎么办呢?模仿刚才的写法肯定是行不通的,因为编译器会认为我们想把字符串赋值给第一个num参数,从而报类型不匹配的错误,如图2.34所示。
不过不用担心,Kotlin提供了另外一种神奇的机制,就是可以通过键值对的方式来传参,从而不必像传统写法那样按照参数定义的顺序来传参。比如调用printParams()函数,我们还可以这样写:
printParams(str = "world", num = 123)
此时哪个参数在前哪个参数在后都无所谓,Kotlin可以准确地将参数匹配上。而使用这种键值对的传参方式之后,我们就可以省略num参数了,代码如下:
fun printParams(num: Int = 100, str: String) {
println("num is $num , str is $str")
}
fun main() {
printParams(str = "world")
}
重新运行一下程序,结果如图所示。
现在你已经掌握了如何给函数设定参数默认值,那么为什么说这个功能可以在很大程度上替代次构造函数的作用呢?
回忆一下当初我们学习次构造函数时所编写的代码:
class Student(val sno: String, val grade: Int, name: String, age: Int) :
Person(name, age) {
constructor(name: String, age: Int) : this("", 0, name, age) {
}
constructor() : this("", 0) {
}
}
上述代码中有一个主构造函数和两个次构造函数,次构造函数在这里的作用是提供了使用更少参数来对Student类进行实例化的方式。无参的次构造函数会调用两个参数的次构造函数,并将这两个参数赋值成初始值。两个参数的次构造函数会调用4个参数的主构造函数,并将缺失的两个参数也赋值成初始值。
这种写法在Kotlin中其实是不必要的,因为我们完全可以通过只编写一个主构造函数,然后给参数设定默认值的方式来实现,代码如下所示:
class Student(val sno: String = "", val grade: Int = 0, name: String = "", age: Int = 0) :
Person(name, age) {
}
在给主构造函数的每个参数都设定了默认值之后,我们就可以使用任何传参组合的方式来对Student类进行实例化,当然也包含了刚才两种次构造函数的使用场景。
nt = 0) :
Person(name, age) {
}
在给主构造函数的每个参数都设定了默认值之后,我们就可以使用任何传参组合的方式来对Student类进行实例化,当然也包含了刚才两种次构造函数的使用场景。
> 本文章参考自郭霖的第一行代码——Android(第3版)