1.函数参数值的设置
fun <T> joinToString(collection: Collection<T>, separator: String=".", prefix: String="@", postfix: String="@"): String {
val result = StringBuilder(prefix)
for ((index, element) in collection.withIndex()) {
if (index > 0)
result.append(separator)
result.append(element)
}
result.append(postfix)
return result.toString()
}
println(joinToString(list)) //默认的函数参数值
println(joinToString(list, "|","*","*"))//设置指定的函数参数值
pritnln(joinToString(list,separator=";")//给定任意顺序的参数
输出结果:
@5.10.99@
*5|10|99*
@JvmOverloads:这个注解指示编译器生成Java重载函数,从最后一个开始省略每个参数。
@JvmName:这个注解可以修改文件类名,必须放在文件的开头,包名的前面
@file:JvmName("StringFunction")
package stringsfun joinToString(...):String{...}
调用方法:
import strings.StringFunction
StringFunction.joinToString(...)
1.扩展函数和属性
1.1 扩展函数
接收者类型是由扩展函数定义的,接收者对象是该类型的一个实例
调用该函数:println("Kotlin".lastChar())
在扩展函数中可以直接访问被扩展的类的其他方法和属性,但是扩展函数不能访问私有的或者是受保护的成员
导入和扩展函数
扩展函数,不会自动地在整个项目范围内生效,如果要使用需要导入
import strings.lastChar
import strings.*
val a = "Kotlin".lastChar()
import strings.lastChar as last 可通过as关键字修改导入的类或函数的名称
val b = "Kotlin".last()
扩展函数实质上是静态函数,它把调用对象作为了它的第一个参数,调用扩展函数,不会创建适配的对象或者任何运行时的额外消耗
重写成员函数:
open class View {
open fun click() = println("View clicked")
}
class Button : View() {
override fun click() = println("Button clicked")
}
val view: View = Button()
fun main() {
view.click()
}
Button是View的子类,Button重写了父类的click函数,现在声明类型为View的变量,它可以被赋值为Button类型的对象,当调用该变量的函数,会调用Button中重写的函数输出:Button clicked
不能重写扩展函数:
fun View.showOff() = println("I am a view")
fun Button.showOff() = println("I am a Button")
val view: View = Button()
fun main() {
view.showOff()
}
声明类型为View的变量,当调用该变量的函数输出:I am a view
1.2 扩展属性
声明一个扩展属性:
val String.lastChar: Char
get() = get(length - 1)
声明一个可变扩展属性:
var StringBuilder.lastChar: Char
get() = get(length - 1)
set(value: Char) {
this.setCharAt(length - 1, value)
}
val sb = StringBuilder("Kotlin")
sb.lastChar = '!'
println(sb)
输出结果:
Kotli!
2.处理集合:可变参数、中缀调用和库的支持
2.1 可变参数:让函数支持任意数量的参数
2.2 键值对的处理:中辍调用和解构声明
val map = mapOf(1 to " One ", 2 to "two", 4 to "four")
to不是内置的结构,是一种特殊函数调用,称为中辍调用。
调用方式:1.to("One")
val s = 2 to "1"
中辍调用可以与只有一个参数的函数一起使用,无论是普通函数还是扩展函数,要允许使用中辍符号调用函数,需要使用infix修饰符来标记:
infix fun Any.to(other: Any) = Pair(this, other)
3.字符串和正则表达式的处理
3.1 分割字符串
println("12.345-6.A.。".split("\\.|-".toRegex()))
println("12.345-6.A.。".split(".", "-"))
[12, 345, 6, A, 。]
3.2 正则表达式和三重引号的字符串
使用String的扩展函数来解析文件路径
println(parsePath("C:/Document/files/ppts/education.aspx"))
fun parsePath(path: String) {
val directory = path.substringBeforeLast("/")
val fullName = path.substringAfterLast("/")
val fileName = fullName.substringBeforeLast(".")
val extension = fullName.substringAfterLast(".")
println("Dir:$directory,fullName:$fullName,fileName:$fileName,extension:$extension")
}
输出结果:
Dir:C:/Document/files/ppts,fullName:education.aspx,fileName:education,extension:aspx
通过正则表达式解析文件路径
fun parsePath(path: String) {
val regex = """(.+)/(.+)\.(.+)""".toRegex()
val matchResult = regex.matchEntire(path)
if (matchResult != null) {
val (directory, fileName, extension) = matchResult.destructured
println("Dir:$directory,fileName:$fileName,extension:$extension")
}
}
(.+)/ : 所有前面斜线的目录
(.+)\.: 最后一个点前的文件名
(.+): 拓展名
4.让代码更整洁:局部函数和扩展
带重复代码的函数:
class User(val id: Int, val name: String, val address: String)
fun saveUser(user: User) {
if(user.name.isEmpty())
throw IllegalArgumentException("Can not save user ${user.id}: empty Name")
if(user.address.isEmpty())
throw IllegalArgumentException("Can not save user ${user.id}: empty Address")
}
局部函数中访问外层函数的参数
class User(val id: Int, val name: String, val address: String)
//提取逻辑到扩展函数
fun User.validateBeforeSave() {
fun validate(value: String, fieldName: String) {
if (value.isEmpty())
throw IllegalArgumentException("Can not save user ${id}: empty $fieldName")
}
validate(name, "Name")
validate(address, "Address")
}
fun saveUser(user: User) {
user.validateBeforeSave()
}
扩展函数也可以被声明为局部函数
小结:
-
Kotlin没有定义自己的集合类,而是在Java集合类的基础上提供API
-
Kotlin可以给函数参数定义默认值,这样降低了重载函数的必要性,也让函数调用更易读
-
函数和属性可以直接在文件中声明,不仅仅在类中作为成员
-
Kotlin可以用扩展函数h和属性来扩展任何类的API,包括在外部库中定义的类,不需要修改源码,也没有运行开销
-
中辍调用提供了处理单个参数,类似调用运算符方法的简明语法
-
字符串和正则表达式都有方便的字符串处理函数
-
局部函数可以保持代码整洁,避免重复