函数的定义与调用(三)

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,包括在外部库中定义的类,不需要修改源码,也没有运行开销

  • 中辍调用提供了处理单个参数,类似调用运算符方法的简明语法

  • 字符串和正则表达式都有方便的字符串处理函数

  • 局部函数可以保持代码整洁,避免重复

 

   

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值