最近在学习 Kotlin 将官方出的练习题做了一遍,将答案以及做题的时候的一些思考记录于此:
开始
执行:git clone [email protected]:Kotlin/kotlin-koans.git
,使用 Idea 打开项目。
1 转换Java代码
fun task1(collection: Collection<Int>): String {
val sb = StringBuilder()
sb.append("{")
val iterator = collection.iterator()
while (iterator.hasNext()) {
val element = iterator.next()
sb.append(element)
if (iterator.hasNext()) {
sb.append(", ")
}
}
sb.append("}")
return sb.toString()
}
2 命名参数
fun task2(collection: Collection<Int>): String {
return collection.joinToString(prefix = "{",postfix = "}")
}
如果之前你了解过 Python,很容易理解这一点。在 Kotlin 中,我们可以为为参数设置默认值来避免书写大量重载方法,在使用时,我们可以根据自己的需要按照 参数名 = 参数
这样的方式填写需要的参数,使用命名参数时可以忽略参数顺序。如果参数中包含没有使用命名的参数,那这些参数任然遵循方法签名的顺序。
3 默认参数
fun foo(name: String, number: Int = 42, toUpperCase: Boolean = false): String = (if (toUpperCase) name.toUpperCase() else name) + number
fun task3(): String {
return (foo("a") +
foo("b", number = 1) +
foo("c", toUpperCase = true) +
foo(name = "d", number = 2, toUpperCase = true))
}
4 Lambda 表达式
fun task4(collection: Collection<Int>): Boolean {
return collection.filter {
it%2==0
}.isEmpty().not()
}
过滤函数: filter{(T) -> Boolean}
根据传入的判断函数返回一个新的 List 集合
5 字符串模板
fun task5(): String = """\d{2} ${month} \d{4}"""
在 kotlin 中,我们可以在字符串中使用 ${}
来包含一个变量或是一个表达式,如果只是一个变量的情况,可以省略花括号。
6 数据类
data class Person(var name:String,var age :Int)
fun task6(): List<Person> {
return listOf(Person("Alice", 29), Person("Bob", 31))
}
7 可空类型
要知道 Kotlin 最大的特点就是空安全,除非我们主动生命,不然所有的对象都是不可为空的。申明一个可空类型的方法十分简单,只需要在类型声明后面加上 ?
fun sendMessageToClient(client: Client?, message: String?, mailer: Mailer) {
client?.personalInfo?.email?.let {email->
message?.let {
mailer.sendMessage(email,it)
}
}
}
class Client (val personalInfo: PersonalInfo?)
class PersonalInfo (val email: String?)
interface Mailer {
fun sendMessage(email: String, message: String)
}
使用 ?.let{}
可以让我们安全的调用可空类型
8 智能转型
fun eval(e: Expr): Int =
when (e) {
is Num -> {
e.value
}
is Sum -> {
eval( e.left)+ eval(e.right)
}
}
when 表达式可以帮助我们智能转型,当传入的对象在通过 is xxx 判断之后,将自动的转型成这个类型,我们可以直接使用,而无需在显示转型。
9 扩展函数
fun Int.r(): RationalNumber = RationalNumber(this,1)
fun Pair<Int, Int>.r(): RationalNumber = RationalNumber(first,second)
扩展函数的声明与使用都非常简单,使用 fun 类名.函数名(参数...):返回值
的方式即可声明一个扩展函数,调用也十分方便,就像调用这个类的自有函数一样自然。
10 object 表达式
fun task10(): List<Int> {
val arrayList = arrayListOf(1, 5, 2)
Collections.sort(arrayList, object :Comparator<Int>{
override fun compare(o1: Int, o2: Int): Int {
return o2-o1
}
})
return arrayList
}
在 Java 中我们通常使用 new XXXInterface(){}
来创建一个接口或是抽象类的匿名内部类,但是在 Kotlin 中没有 new
这个关键字,我们可以使用 object 关键字来创建一个接口或是抽象类的实现对象。当然,通常的,面对这种仅有一个方法需要实现的接口,我们完全可以使用 Lambda 表达式来书写,这样代码更加简洁。
11 SAM 转换
fun task11(): List<Int> {
val arrayList = arrayListOf(1, 5, 2)
Collections.sort(arrayList, { x, y -> y-x })
return arrayList
}
当一个对象需要实现了一个 SAM(单一抽象方法)接口,你可以使用 Lambda 表达式来代替他。另外,如果一个方法的最后一个参数是一个 SAM 接口,我们可以将 {}
包裹的 Lambda 表达式放到括号外面,效果如下:
Collections.sort(arrayList) { x, y -> y-x }
12 集合扩展
fun task12(): List<Int> {
return arrayListOf(1, 5, 2).sortedDescending()
}
对 List 降序排列,在 kotlin 中只需要调用它的扩展方法即可!