初识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、扩展:

所谓扩展,就是对已经有的类,但是不能修改源码的这种去增加一些方法。添加方法的时候要注意尽量不要和类中已经有的方法重名,如果非要重名,那类型也不要相同。简单来说就是别一毛一样。举个例子:咱们要Toast一下,但是每次写吐司都写的比较长,怎么办呢?咱们就用这个类的扩展,对Context类写一个Toast扩展:

    fun Context.ToastKotlin(message: String) {
        Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
    }

同样使用也很简单(这是一个recyclerview的点击事件):

        mTestAdapter!!.setOnItemClickListener(OnItemClickListener { view, position ->
            this.ToastKotlin("adapter的点击事件${position}")
        })

尴尬的事情出现了,在Kotlin中已经帮咱们写了这个扩展方法了,相信大家调用的时候会发现这个问题,但是大家懂了这个意思就好了。然后咱们看一下其他的例子具体的写法:

//扩展函数: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,可能对概念以及用法的认识有偏差,如有错误,希望大家给予指正!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容