写点什么

Kotlin 函数竟然如此简洁

作者:Silently9527
  • 2024-09-12
    四川
  • 本文字数:2666 字

    阅读完需:约 9 分钟

Kotlin函数竟然如此简洁

定义函数

在上一节中其实已经使用到了函数,这里来正式看看 Kotlin 中定义一个函数,包含返回类,以及参数


fun max(a: Int, b: Int): Int {    return if (a > b) a else b;}
复制代码


注意,max 方法中的 if 没有使用 return,这需要提一下,Kotlin 中的 if 是表达式,有返回值,默认表达式的最后一行就是返回值;try-catch 也是表达式,例子在上一节中已经展示了


Kotlin 没有再新写集合类,依旧使用的是 Java 的集合类,只是对 Java 的集合类进行了增强,


fun testFun() {    val siteInfo = listOf("Herman", "http://herman7z.site")    println(siteInfo)}
复制代码



listOf 方法就是 Kotlin 的增强,具体如何实现的后面在来看, kotlin 也对不同类型的集合实现了 toString, 输出更能够看的懂

命名参数、默认值参数

对上面的函数 testFun 添加两个参数, 代码如下:


fun testFun(a: String = "None", b: String = "None") {    val siteInfo = listOf("Herman", "http://herman7z.site", a, b)    println(siteInfo)}
复制代码


在 Java 中是不能够给函数的参数指定默认值的, Kotlin 实现了这点, 上面的函数 a、b 如果在调用方没有传入参数时就使用默认值


接下来我们看看调用这个函数


  1. 由于有默认值,所以我们可以不需要传入参数 testFun()输出的结果:


[Herman, http://herman7z.site, None, None]
复制代码


  1. 常规方式调用必须按照参数的顺序 testFun("aaa", "bbb")


[Herman, http://herman7z.site, aaa, bbb]
复制代码


  1. 可以指定给某个参数赋值,比如 testFun(b = "123")


[Herman, http://herman7z.site, None, 123]
复制代码


注意:参数的默认值是被编译到被调用的函数中的,而不是调用方.

顶层函数

Java 是面向对象的语言,所有的方法都必须存在在某个类中作为成员方法,但是在实际的使用过程中会发现有些方法不适合作为任何类的成员方法,所以才有了很多的 Utils


在 Kotlin 中可以不再需要使用 Utils, 可以把这些函数直接放在代码文件(文件名:Chapter02.kt)的顶层, 如下:


class Chapter02 {}
fun testFun(a: String = "None", b: String = "None") { val siteInfo = listOf("Herman", "http://herman7z.site", a, b) println(siteInfo)}
复制代码


在实际编译后会更具文件名称生产一个 Java 类 Chapter02Kt, 其中testFun会被编译出这个 Java 类的静态方法, 所以如果在 Java 类中需要调用 Kotlin 的 Chapter02



public class Test { public static void main(String[] args) { Chapter02Kt.testFun("aaa","bbb"); }}
复制代码

顶层属性

与函数一样,属性也可以放在顶层,最终也会被编译成类的静态属性, 如果属性使用的val那么就只有一个 getter 方法, 如果使用的var就会有 getter、setter;


在 Java 中使用public static final来定义一个常量, Kotlin 中使用 const来实现


const val HERMAN_BLOG = "http://herman7z.site"class Chapter02 {}
复制代码


在 Java 中调用


public class Test {    public static void main(String[] args) {        System.out.println(Chapter02Kt.HERMAN_BLOG);    }}
复制代码

扩展函数

Kotlin 的另一个特点就是可以给现有的类创建扩展函数和属性,无需修改原来的类,这里我们定一个类 Chapter02


class Chapter02 {}
复制代码


然后我们通过扩展函数的方式来给 Chapter02 添加一个getAddress方法


fun Chapter02.getAddress():String ="http://herman7z.site"
复制代码


这里可以看到扩展函数和普通函数的定义唯一不同就是多了个前缀Chapter02,指定是给哪个类添加扩展函数


fun main() {   println(Chapter02().getAddress())}
复制代码


接下来把这个例子在稍微改动一点点,我们在Chapter02类中添加一个方法buildAddress, 然后在扩展函数中可以使用this直接调用这个方法,所以扩展函数可以使用this来引用类的原来的属性或者方法.


class Chapter02 {    fun buildAddress(): String {        return "http://herman7z.site";    }}
fun Chapter02.getAddress(): String = this.buildAddress();
fun main() { println(Chapter02().getAddress())}
复制代码


注意:

  1. 扩展函数不能够引用类的私有和受保护的成员

  2. 扩展函数是 Kotlin 提供的高级语法糖,实质上扩展函数会被编译成 Java 类的静态函数,他会把调用对象作为静态函数第一个参数;所以如果在 Java 中调用扩展函数需要把目标对象传入到静态函数

  3. 扩展函数的静态性质导致扩展函数是不能够被继承, 不能够被重写


对于我们定义的扩展函数,Kotlin 不会自动全局导入,需要我们在使用的时候导入


import org.herman.kotlin.getAddress
fun main() { Chapter02().getAddress()}
复制代码


由于项目会定义很多扩展函数,所以可能会出现命名冲突,出现这种情况的时候可以是用 as 关键字


import org.herman.kotlin.getAddress as addr
fun main() { Chapter02().addr()}
复制代码

扩展属性

扩展属性可以为现有的类添加属性, 使用的属性语法来访问, 尽管被称为属性,但是不会有任何状态,不会初始值,因为静态的性质,没有合适的地方来存储值.


依旧是对 Chapter02 类进行扩展, 在使用时与访问普通属性没有区别


val Chapter02.name: String    get() = "Herman"    fun main() {    println(Chapter02().name)}
复制代码

可变参数

函数的参数可以是任意个数, 使用关键字vararg, 来看看 kotlin 库函数 listOf 如何使用的可变参数


public fun <T> listOf(vararg elements: T): List<T> = if (elements.size > 0) elements.asList() else emptyList()
复制代码


使用的方式很简单


fun main(args: Array<String>) {    val col = listOf("a", "b", "c", *args)}
复制代码


这里使用了展开运算符*, 这个功能 Java 没有

中辍调用

在中辍调用中,没有添加额外的分隔符,函数名后面直接给参数,什么的函数需要使用关键字infix修饰


我们先来给 Int 类添加一个扩展函数add, 使用关键字infix修饰这个函数使之支持中辍调用


infix fun Int.add(value: Int): Int = this.plus(value)
fun main() { println(10.add(5)) //普通调用 println(10 add 5) //中辍调用}
复制代码

局部函数

在 Java 类中,可以抽离很多的小的函数,但是可能这些函数的作用域可以更小, 在 Kotlin 中就可以使用局部函数来处理


class User(val name: String, val address: String)
fun save(user: User) { fun validate(value: String, field: String) { if (Objects.isNull(value) || value.isEmpty()) { throw IllegalArgumentException("$field can not empty") } }
validate(user.name,"name") validate(user.address,"address") //save user}
复制代码


在这个例子中validate就是一个局部函数,作用域只在 save 方法中; 如果使用 Java 来实现validate函数就只能放到类级别,与 save 同级, 但是这个validate方法只会 save 方法调用,就放大了函数的作用域

发布于: 刚刚阅读数: 5
用户头像

Silently9527

关注

公众号:贝塔学JAVA 2018-05-09 加入

Simple Programmer, Make the complex simple

评论

发布
暂无评论
Kotlin函数竟然如此简洁_Java_Silently9527_InfoQ写作社区