Kotlin基础二

414 阅读7分钟

内容:

  • 函数的调用方试,重载方消除静态方法静态属性
  • 给别的类扩展函数扩展属性
  • 局部函数和扩展
  • 集合创建集合的一些扩展特性
  • 字符串的一些扩展特性

一函数

上一篇我们简单介绍了如何声明一个函数,这里我们介绍一下函数调用方式函数的重载 和java的区别;

1.1函数的调用方式

声明一个函数 

fun setName(name: String) {
}

在java中我们直接调用

setName("张三")

而在kotlin中我们还可以显示出参数的名字,像这样

setName(name = "张三")

这样的好处是,我们看到一个方法,会更加快速的清楚这个参数的意思,可读性会更强。

1.2函数的重载

在java中如果参数多少不一样,我们每次都要写一堆同名方法,像这样:

fun setName(name: String) {
}

fun setName(name: String, age: Int) {
    
}

而在kotlin我们可以通过设置,来通过一个方法去表现出来重载,替换成这样:

fun setName(name: String, age: Int = 1) {

}

而调用一个参数的时候,并不会报错。

注意:当你这样写重载函数,你会遇到一个再java中调用的问题,这时候需要使用@JvmOverloads注解去注解一下你Kotlin中的方法,这样就能在java中随意调用任何参数的重载方法。像这样

#Kotlin代码
class Dog{
    @JvmOverloads
    fun setName(name: String, age: Int = 1) {
    }
}

#java中调用,没有问题
Dog dag = new Dog();
dag.setName("222");

1.3 消除静态方法

java作为一门面向对象的语言,需要所有的代码都写在类内。而kotlin可以把方法写到类外边,虽然编译的时候还是编译到类内,但是,这种呈现方式更加简洁:
package utils

fun aa(name: String): String {
    return name
}

Kotlin中调用:

val aa = utils.aa("张三")
Log.e("rrrrr",aa)

java中调用:

utils.DogKt.setName("张三");

延伸:同理,声明在类外边的订层属性,可以做为静态属性。像这个值就会被存储到一个静态的字段中。但是这种顶层方法和顶层属性一般用作静态工具类,比如单例的时候就不能这样写。后边会讲单例。

二 扩展函数和扩展属性

2.1扩展函数:可以理解成它就是一个类的成员函数,不过定义在类的外面。但必须结合顶层函数去扩展。
package utils

fun String.lastChareee(): Char {
    return this.get(this.length-1)
}

调用

Log.e("rrrrrrr", "Kotlin".lastChareee().toString())

2.2 java代码中调用扩展函数

实质上,扩展函数是静态函数的语法糖。我们在java中像调用静态方法一样去调用

utils.DogKt.lastChareee("Kotlin");

2.3 扩展函数的静态性质也决定了扩展函数不能被子类重写。但可以被子类继承。

open class Father

class Son1:Father()

package utils

import android.util.Log
import xifuyin.tumour.com.a51ehealth.kotlin_book.Father

fun Father.setName(){
    Log.e("rrrr","调用父类的方法")
}

这时,子类也可以调用setName方法。

可以给基类和子类都分别定义一个同名的扩展函数,当这个函数被调用时,它会用到哪一个呢?

添加子类扩展代码如下:

package utils

import android.util.Log
import xifuyin.tumour.com.a51ehealth.kotlin_book.Father
import xifuyin.tumour.com.a51ehealth.kotlin_book.Son1

fun Father.setName(){
    Log.e("rrrr","调用父类的方法")
}
fun Son1.setName(){
    Log.e("rrrr","调用子类的方法")
}

这个时候调用:

var s :Father= Son1()
s.setName()

var s = Son1()
s.setName()

调用的方法确是不一样的。

它是由该变量的静态类型所决定的,而不是这个变量的运行时类型。


注意:如果一个类的成员函数和扩展函数有相同的签名,那么将会调用类的才成员方法。

2.4扩展属性

我们上一篇已经知道,属性的声明默认都是提供get和set方法的,所以我们扩展属性,还是要依赖内部的方法。基本没有什么用。我也不会。。。。

三 局部函数和扩展

      对于java而言,只有局部变量,没有局部方法,也就是方法中不能再写方法。在kotlin中方法内可以写方法,这个内部方法叫做局部方法。

我们去请求一个数据,要求两个参数都不能是空字符串,我们可以这样写

open class Father(var name: String, var address: String) {}
fun save2(fa: Father) {

    fun validate(value: String): Boolean {
        if (value.isEmpty()) {
            Log.e("rrrr", "内部函数")
            return false
        }
        return true
    }

    if (validate(fa.name) && validate(fa.address)) {
        Log.e("rrrr", "外部函数")
        //请求数据
    }

}
这样代码功能性更更加整体,而不会变得零散难读。

近一步改变,如下:

open class Father(var name: String, var address: String) {}

fun Father.validate(): Boolean {
    fun validate2(value: String): Boolean {
        if (value.isEmpty()) {
            Log.e("rrrr", "内部函数")
            return false
        }
        return true
    }

    return validate2(name) && validate2(address)
}

使用起来更加具有可读性:

var f = Father("", "")
if (f.validate()) {

}

在Kotlin中集合

4.1集合的创建

在第一篇中我们简单了解了创建list集合和set集合,这里我们更进一步去了解集合的创建和特性。 kotlin中的集合类和java中的集合类是一样的,并且提供了简单的创建方式:

    创建java.util.Arrays$ArrayList集合 : var cc = listOf<String>("aa", "bb")

    创建java.util.ArrayList集合: var cc = arrayListOf<String>("aa", "bb")

    创建java.util.LinkedHashSet集合: var aa = setOf<String>("aa", "bb")

    创建java.util.HashSet集合: var bb = hashSetOf<String>("bb", "aa")

    创建java.util.Collections$SingletonMap集合:val mapOf = mapOf(1 to "one")

    创建java.util.HashMap集合:val map=hashMapOf(1  to “one”)

注意to并不是一个特殊的结构,而是一个普通函数。

4.2 集合的扩展特性

尽管Kotlin的集合类和Java的集合类完全一致,但Kotlin提供了更多操作集合的方法:

var cc = listOf<Int>(1, 2)
cc.last()//获取集合中最后一个数据
cc.max()//获取集合中最大的一个数
我们感兴趣的是它是怎么工作的:尽管它们是Java库类的实例,为什么在Kotlin中能对集合有这么多丰富的操作。现在答案很明显了:因为函数last和max都被声明成了扩展函数。你可能会想知道,在Kotlin标准库中学习所有内容的最佳方式。这个并没有必要,在你需要操作集合或任何其他对象的时候,根据提示,会展示给你所有可用的函数,包括成员函数和扩展函数。

4.3.让函数支持任意多参数

public fun <T> arrayListOf(vararg elements: T): ArrayList<T>
        = if (elements.size == 0) ArrayList() else ArrayList(ArrayAsCollection(elements, isVarargs = true))

这是arrayListOf方法的内部扩展实现,这里有一个关键字vararg,这个关键之表示这个参数是可变化的。

private fun add(vararg a: Int) {

}

这个方法就是可以传递任意多的参数。

4.4map中的to函数解释

代码中的单词to不是内置的结构,而是一种特殊的函数调用,被称为中缀调用。

在中缀调用中,没有添加额外的分隔符,函数名称是直接放在目标对象名称和参数之间的。
以下两种调用方式是等价的:
1.to("one")
1 to "one"
中缀调用可以与只有一个参数的函数一起使用,无论是普通的函数还是扩展函数。要允许使用中缀符号调用函数,需要使用infix修饰符来标记它。下面是一个简单的to函数的声明:

infix fun Any.to(other:Any)=Pair(this,other) 

看到这里,你应该知道to的内部实现原理,还是创建一个pair对象。

五.字符串的一些扩展特性

Kotlin字符串与Java字符串完全相同。Kotlin通过提供一系列有用的扩展函数,使标准Java字符串使用起来更加方便。

5.1分割字符串

val split = "12.345-6.A".split("\\.".toRegex())

这是后打印出来结果:[12, 345-6, A]

注意,你可以指定字符参数,并写入“12.345-6.A".split(‘.’,'-'),一起去分割。

小结:

1.函数的可以使用显示变量和隐试变量去调用

2.函数的重载只需要设置一个,其余的参数可以设置成默认值,和java交互使用@JvmOverloads去注解

3.函数的静态写法,写到类外边,不用花括号包裹

4.函数的扩展,实质就是静态语法糖的提现

5.扩展的函数子类可以继承,但不能重写,调用哪个要看生命的静态类型

6.局部函数的写法和使用

7.常用集合的创建

8.集合的扩展方法to

9.字符串的分割.的问题的解决,和分割方法的重载