初识Kotlin(下)

上一篇《初识Kotlin(上)》

在上一篇文章中介绍了Kotlin的一些基本语法,包括变量、常量的定义、控制循环语句、函数的定义及使用、类的定义、方法和属性、继承、数据类、枚举类、异常处理、类型检查和转换等部分的内容。这这篇文章中记录一下接口、泛型以及扩展的部分内容。
接上篇继续

8、接口:

在java语言中也有接口的定义,和kotlin中相比相差不大。那什么是接口呢?
接口就是对方法或者属性的实现标准。这样说可能有点抽象。举个例子:每一个自然人呢都有一个名字,然后现在有一个歪果仁想要加入中国的国籍,想要以后在中国发展。那咱们定义一个人(Person)的类,然后再定义一个歪果仁(ForigChinese)的类去继承人(Person)的类。
这时候这个歪果仁要加入中国的国籍,那怎么办呢,我们不能在Person类中添加加入中国国籍的方法。所以我们去写一个接口,定义一个加入中国国籍的方法,让想要加入中国国籍的歪果仁去实现这个方法。这样,这个歪果仁的实例就可以去调用加入中国国籍的方法了。
具体的咱们来看下边的代码:
首先定义一个Person类,因为这个类需要被其他的类继承,所以使用open关键字来修饰

   open class Person {
        var name = ""
    }

然后去定义一个可以生存的接口:

    interface Livable {
        //接口中的属性和方法不能初始化
        var hasSkill: Boolean//接口中的属性
        fun addChina() //接口中的方法
        //接口中的方法可以有默认实现,通常指该方法是固定不变的
        fun SpeakChinese() {
            LogUtils.Loge("接口中的默认方法:我可以说中文")
        }
    }

然后定义一个可以在中国生存的接口:

    interface ChinaLivable {
        //接口中的属性不可初始化
        val hasJobOffer: Boolean
        //接口中可以有get方法,通常用于增加一个常量属性
        val visaCatagory: String
            get() = "工作offer"
        //接口中的属性
        var city: String
    }

然后去定义一个歪果仁的类继承Person类,并且实现生存接口和在中国生存的接口:

    class ForigChinese : Person(), Livable, ChinaLivable {
        override var hasJobOffer: Boolean = true
        override var city: String = "北京"
        override var hasSkill: Boolean = true
        override fun addChina() {
            LogUtils.Loge("我叫${name}我要加入中国国籍")
        }
    }

这时候,这个歪果仁就有了生存的能力,并且有了在总过生存的能力。所以他就能加入中国国籍了。

        var mForigChinese = ForigChinese()
        mForigChinese.name = "小米"
        mForigChinese.city = "北京"
        mForigChinese.hasJobOffer = true
        mForigChinese.hasSkill = true
        mForigChinese.addChina()
        mForigChinese.SpeakChinese()
        LogUtils.Loge("接口名称:" + mForigChinese.name)
        LogUtils.Loge("接口城市:" + mForigChinese.city)
        LogUtils.Loge("接口是否有工作:" + mForigChinese.hasJobOffer)
        LogUtils.Loge("接口是否有生存技能:" + mForigChinese.hasSkill)

然后看一下Log:

11-16 15:49:22.968 4994-4994/com.example.lql.kotlindemo E/###: 我叫小米我要加入中国国籍###
11-16 15:49:22.968 4994-4994/com.example.lql.kotlindemo E/###: 接口中的默认方法:我可以说中文###
11-16 15:49:22.968 4994-4994/com.example.lql.kotlindemo E/###: 接口名称:小米###
11-16 15:49:22.968 4994-4994/com.example.lql.kotlindemo E/###: 接口城市:北京###
11-16 15:49:22.968 4994-4994/com.example.lql.kotlindemo E/###: 接口是否有工作:true###
11-16 15:49:22.968 4994-4994/com.example.lql.kotlindemo E/###: 接口是否有生存技能:true###

我们发现我们给歪果仁(ForigChinese )类添加了两个能力,一个是生存的能力,一个是在中国生存的能力,但是ForigChinese类本身看起来并没有复杂。所以,接口可以给 类附加能力,并且让类看起来很简洁。
还有一点,这个能力并没有在父类中去实现,所以通过接口的方法来实现某些功能,是可以选择的,如果我不想要在中国生存的能力,就可以不实现这个接口就好了。使用起来很方便。

9、泛型:

泛型就是让一个函数或者类能更加通用,首先咱们看一下系统给提供的一下泛型的方法。

//定义一个Int类型的数组
var intList = arrayOf(1, 2, 3, 4, 5, 6, 7, 10)
//定义一个String类型的数组
var stringList = arrayOf("1","2","3","4","5","6","7","9")

我们发现arrayOf方法,我们既可以传Int类型的参数进去,也可以传String类型的参数进去。这就是泛型方法的体现。
在我们定义方法或者类的时候,有时候也要考虑这个因素进去,我们写了一个工具类,能不能传递不同类型的传输进去呢?这可以让方法在更多的情境下使用。

9.1基本泛型

然后我们来看一下泛型在Kotlin中的写法:

    //定义一个泛型函数: <T> T表示一个占位符
    fun <T> showText(para: T) {
        LogUtils.Loge("泛型入参:" + para.toString())
    }

然后调用这个方法:

 showText(3)
showText("123")

Log:

11-16 16:02:29.258 4994-4994/com.example.lql.kotlindemo E/###: 泛型入参:3###
11-16 16:02:29.258 4994-4994/com.example.lql.kotlindemo E/###: 泛型入参:123###

我们可以看到对与一个方法showText()传递了两种不同类型的参数进去。

9.2约束泛型:

现在我们有一个数组

arrayOf(1, 2, 3, 4, 5, 6, 7, 10, 11)

我们相对这个数组求和,这个时候我们参数都是Int类型的,我们可以直接调用.sum()方法去求和。
然后咱们把数组改一下

arrayOf(1, 2, 3, 4, 5, 6, 7, 10, 11.11)

这样,里边多了一个double类型的元素。这时候就没办法调用.sum()方法了。然后我们使用约束泛型去实现一个求和方法:

 //下边就是泛型约束:<泛型占位符: 类型>  把泛型约束在Number类型中
    fun <T : Number> sum2(vararg number: T): Double {
        return number.sumByDouble { it.toDouble() }
    }

通过上边的注释,大家应该能看懂这个约束泛型的意思。就不再解释了。

9.3多重约束泛型:

写法就是把多个约束用where修饰,中间使用“ , ”隔开,写在函数体之前。
例子:把数组中大于某个元素的部分都取出来并升序排列

    //Comparable 可比较的,大于、小于、等于
    fun <T> biggerPart(list: Array<T>, threhold: T): List<T>  where T : Number, T : Comparable<T> {
        return list.filter { it >= threhold }.sorted()
    }

来看一下试用方法:

//多重约束
        val biggerPart = biggerPart(arrayOf(99, 1, 2, -2, 88, 1024, 888), 3)
        for (i in biggerPart) {
            LogUtils.Loge("多重约束:${i}")
        }

Log:

11-16 16:02:29.258 4994-4994/com.example.lql.kotlindemo E/###: 泛型约束:38.11###
11-16 16:02:29.258 4994-4994/com.example.lql.kotlindemo E/###: 多重约束:88###
11-16 16:02:29.258 4994-4994/com.example.lql.kotlindemo E/###: 多重约束:99###
11-16 16:02:29.258 4994-4994/com.example.lql.kotlindemo E/###: 多重约束:888###
11-16 16:02:29.258 4994-4994/com.example.lql.kotlindemo E/###: 多重约束:1024###
10、扩展:

所谓扩展,就是对已经有的类,但是不能修改源码的这种去增加一些方法。添加方法的时候要注意尽量不要和类中已经有的方法重名,如果非要重名,那类型也不要相同。简单来说就是别一毛一样。
看一下具体的写法:

//扩展函数:fun 接受者类型.新扩展函数名(参数类别){//函数实现}
    //1、函数扩展
    fun Int.square(): Int {
        return this * this
    }

    //2、泛型函数扩展:求数字型数组中的最大元素
    fun <T> Array<T>.biggest(): T
            where T : Number,
                  T : Comparable<T> {

        var biggest = this[0]
        for (t in this) {
            if (t > biggest) {
                biggest = t
            }
        }
        return biggest
    }


    //    3、属性的扩展(普通属性)
    val Int.next: Int
        get() = this + 1

    //4、泛型属性    数字类型的半径   的面积
    val <T : Number> T.area: Double
        get() = 3.1425926 * this.toDouble() * this.toDouble()

使用:

 LogUtils.Loge("函数扩展:" + 3.square())

        val a = arrayOf(1, 2, 3, 4, 5, 8)
        LogUtils.Loge("求最大" + a.max())
        val biggest = a.biggest()
        LogUtils.Loge("自己写一个求最大:" + biggest)

        LogUtils.Loge("属性扩展:" + 3.next)
        LogUtils.Loge("属性泛型扩展:" + 3.area)
        LogUtils.Loge("属性泛型扩展:" + 'B'.toByte().area)

Log:

11-16 16:16:59.348 4994-4994/com.example.lql.kotlindemo E/###: 函数扩展:9###
11-16 16:16:59.348 4994-4994/com.example.lql.kotlindemo E/###: 求最大8###
11-16 16:16:59.348 4994-4994/com.example.lql.kotlindemo E/###: 自己写一个求最大:8###
11-16 16:16:59.348 4994-4994/com.example.lql.kotlindemo E/###: 属性扩展:4###
11-16 16:16:59.348 4994-4994/com.example.lql.kotlindemo E/###: 属性泛型扩展:28.283333399999997###
11-16 16:16:59.348 4994-4994/com.example.lql.kotlindemo E/###: 属性泛型扩展:13689.1333656###

这一部分,大家一看就知道具体的意思了,就不解释了。

好啦,通过两篇文章记录了一下Kotlin中变量的定义、元组的使用、循环控制流的使用、类的相关使用、异常处理、接口、泛型和扩展部分的内容。最开始学习Kotli就先聊这么多。我需要继续学习了。还是上一篇中的那句话,刚开始学习使用Kotlin,可能对概念以及用法的认识有偏差,如有错误,希望大家给予指正!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值