• Kotlin 扩展


    1.官方文档

      https://kotlinlang.org/docs/reference/extensions.html

      https://www.kotlincn.net/docs/reference/extensions.html 中文

    1.1 作用

    • 可以在不修改某个类的代码的情况下,对该类扩展,添加扩展函数,扩展属性。
    • 可以在类内、全局作用域内对其它类扩展
    • 扩展的函数、属性可以访问被扩展类的成员。
    • interface,sealed,data,enum 也可以扩展

    1.2 示例,对Context添加Toast功能

    1     fun Context.toast(msg : String, duration : Int = Snackbar.LENGTH_SHORT){
    2         Snackbar.make(window.decorView,msg,duration).show()
    3     }
    4 
    5     override fun onTrimMemory(level: Int) {
    6         super.onTrimMemory(level)
    7         baseContext.toast("onTrimMemory")
    8     }

    2.扩展函数

    2.1 自定义类 扩展函数

       函数里面可以使用this,但是不可以用super

     1 open class Base1{
     2     var base = 100
     3 }
     4 open class Source : Base1(){
     5     var COUNT = 1
     6     fun fooooo() : Int {
     7         return super.base.inc()
     8     }
     9 }
    10 
    11 //1.自定义的类 扩展函数,里面可以使用this,但是不可以用super
    12 inline fun Source.addBase(x : Int){
    13 //  var ret = this.COUNT + x + super.base //error,不可以用super
    14     var ret = this.COUNT + x + fooooo()
    15     Log.e(TAG_EXTENSIONS, "count = ${this.COUNT} ,ret = $ret" )
    16 }
    17 fun test1(){
    18     var a = Source()
    19     a.addBase(3)
    20 
    21 }

       结果

    2019-09-05 23:02:27.007 15205-15205/com.example.kotlin E/extensions: count = 1 ,ret = 105

     2.2 扩展函数重载

     1 open class Base1{
     2     var base = 100
     3 }
     4 open class Source : Base1(){
     5     var COUNT = 1
     6     fun fooooo() : Int {
     7         return super.base.inc()
     8     }
     9 }
    10 inline fun Source.addBase(x : Int){
    11 //  var ret = this.COUNT + x + super.base //error,不可以用super
    12     var ret = this.COUNT + x + fooooo()
    13     Log.e(TAG_EXTENSIONS, "count = ${this.COUNT} ,ret = $ret" )
    14 }
    15 //2.扩展函数的重载版本
    16 inline fun Source.addBase(string : String){
    17     var x = string.toInt()
    18     var ret = this.COUNT + x + fooooo()
    19     Log.e(TAG_EXTENSIONS, "count = ${this.COUNT} ,ret = $ret" )
    20 }
    21 fun test2(){
    22     var a = Source()
    23     a.addBase(3)
    24     a.addBase("1000")
    25 
    26 }

      结果

    2019-09-05 23:52:06.449 16731-16731/com.example.kotlin E/extensions: count = 1 ,ret = 105
    2019-09-05 23:52:06.449 16731-16731/com.example.kotlin E/extensions: count = 1 ,ret = 1102

     2.3 预定义类 扩展函数

     1 open class Base1{
     2     var base = 100
     3 }
     4 open class Source : Base1(){
     5     var COUNT = 1
     6     fun fooooo() : Int {
     7         return super.base.inc()
     8     }
     9 }
    10 //3.预定义的类 扩展函数
    11 fun Int.add(source: Source) =  source.base.dec()
    12 
    13 fun test3(){
    14     var a = Source()
    15 
    16     val int = 100
    17     var ret = int.add(a)
    18     Log.e(TAG_EXTENSIONS,"ret = $ret")
    19 }

      结果

    2019-09-05 23:52:06.618 17524-17524/com.example.kotlin E/extensions: ret = 99

    2.4 final的类也可以扩展函数

     1 //4.final的类也可以扩展函数
     2 fun String.add(ext : String?) : String?{
     3     return  toString() + " $ext"
     4 }
     5 fun test4(){
     6     var str1 = "hello"
     7     var str2 = "world"
     8     var str3 = str1.add(str2)
     9     Log.e(TAG_EXTENSIONS,"str3 = $str3")
    10 }

      结果

    2019-09-05 23:52:27.618 17524-17524/com.example.kotlin E/extensions: str3 = hello world

     2.5 父类的 扩展函数 子类可以使用

     1 //5.父类的 扩展函数 子类可以使用
     2 open class User{
     3     /*protected*/
     4     var age = 22
     5     open fun name(){
     6 
     7     }
     8 }
     9 class EUser : User() {
    10 }
    11 fun User.age() : Int{
    12     return this.age
    13 }
    14 fun EUser.eage() : Int{
    15     return this.age
    16 }
    17 
    18 fun test5(){
    19     var user = User();
    20     var name = user.name()
    21     var age = user.age()
    22     var eUser = EUser()
    23 
    24     age = eUser.age()
    25 //    user.eage()   //error,子类的扩展函数不能用于父类
    26 }

    2.6 扩展函数 与多态

    • 全局作用域的扩展函数不参与多态
     1 //6.全局作用域的扩展函数 不参与多态
     2 open class C6{
     3     open fun f6() = "c6_f6"
     4 }
     5 open class D6 : C6(){
     6     override fun f6() = "d6_f6"
     7 }
     8 
     9 fun C6.foo() = "c6"
    10 fun D6.foo() = "d6"
    11 
    12 fun test6(){
    13     var c6 = C6()
    14     var d6 = D6()
    15     var objC6 : C6 = D6()
    16 
    17     var foo = objC6.foo()
    18     var f6 = objC6.f6()
    19 
    20     Log.e(TAG_EXTENSIONS,"foo = $foo , f6 = $f6")
    21 
    22 }

      结果

    2019-09-05 23:51:00.754 18521-18521/com.example.kotlin E/extensions: foo = c6 , f6 = d6_f6
    • 类内的扩展函数支持多态
     1 fun test6(int: Int){
     2 
     3     open class A
     4 
     5     open class Base {
     6         open fun A.foo() {
     7             Log.e(TAG_EXTENSIONS,"A.foo in Base.")
     8         }
     9         fun caller(a : A) {
    10             a.foo()
    11         }
    12     }
    13     class Derived : Base() {
    14         override fun A.foo() {
    15             Log.e(TAG_EXTENSIONS,"A.foo in Derived")
    16         }
    17     }
    18     var oa = A()
    19     var base = Derived()
    20     base.caller(oa)
    21 
    22 }

      结果

    2019-09-05 08:46:34.293 7868-7868/com.example.kotlin E/extensions: A.foo in Derived

    2.7 接口支持扩展函数

      但是接口实现者不用实现扩展的函数

     1 //7.接口支持扩展函数,,但是不用实现扩展的函数
     2 interface IF1{
     3     fun foo(){
     4         Log.e(TAG_EXTENSIONS,"c7.foo")
     5     }
     6 }
     7 class C7 : IF1{
     8     override fun foo() {
     9         super.foo()
    10         Log.e(TAG_EXTENSIONS,"c7.foo")
    11     }
    12 }
    13 fun IF1.fext(){ //接口实现者不用实现这个扩展函数 fext
    14     Log.e(TAG_EXTENSIONS,"IF1.fext")
    15 }
    16 fun test7(){
    17     var obj = object : IF1{
    18         override fun foo() {
    19             super.foo()
    20         }
    21     }
    22     obj.fext()
    23     var c7 = C7()
    24 
    25     c7.fext()
    26 }

      结果

    2019-09-05 23:51:00.755 18521-18521/com.example.kotlin E/extensions: IF1.fext
    2019-09-05 23:51:00.755 18521-18521/com.example.kotlin E/extensions: IF1.fext

     2.8 扩展函数与成员函数相同

      这时,优先使用类内的同名函数。

     1 //8.扩展函数与成员函数相同时,优先使用类内的同名函数。
     2 open class C8{
     3     var value = 0
     4     inline fun add(v : Int){
     5         this.value += v
     6         Log.e(TAG_EXTENSIONS,"member.add(Int) value = $value")
     7     }
     8 }
     9 fun C8.add(v: Int) {
    10     this.value += v * 2
    11     Log.e(TAG_EXTENSIONS, "extension.add(Int) value = $value")
    12 }
    13 fun C8.add(f: Float) {
    14     this.value += (f * 2).toInt()
    15     Log.e(TAG_EXTENSIONS, "extension.add(Float) value = $value")
    16 }
    17 
    18 internal fun test8(){
    19     var c8 = C8()
    20 
    21     c8.add(2)
    22 
    23     c8.add(3.0f)
    24 
    25 }

      结果

    2019-09-05 12:54:10.717 4584-4584/com.example.kotlin E/extensions: member.add(Int) value = 2
    2019-09-05 12:54:10.717 4584-4584/com.example.kotlin E/extensions: extension.add(Float) value = 8

    2.9 扩展类的伴生对象

     1 //9.扩展类的伴生对象
     2 class C9{
     3     companion object{
     4         fun getNum() = 10
     5     }
     6 }
     7 fun C9.Companion.foo() = 20
     8 
     9 fun test9(){
    10     var num = C9.foo()
    11     Log.e(TAG_EXTENSIONS,"C9.externion static foo = " + num)
    12 }

      结果

    2019-09-05 12:54:10.718 4584-4584/com.example.kotlin E/extensions: C9.externion static foo = 20

    2.10 用扩展重载运算符

     1 data class OP3(var value: Int = 0){
     2     override fun toString() : String {
     3         return value.toString()
     4     }
     5 }
     6 operator fun OP3.plus(op3 : OP3)= OP3(value + op3.value)
     7 operator fun OP3.plus(x : Int)  = OP3(value + x)
     8 operator fun OP3.minus(x : Int) = OP3(value - x)
     9 operator fun OP3.times(x : Int) = OP3(value * x)
    10 operator fun OP3.div(x : Int)   = OP3(value / x)
    11 operator fun OP3.rem(x : Int)   = OP3(value % x)
    12 
    13 operator fun OP3.divAssign(x : Int){
    14     value /= x
    15 }
    16 
    17 fun op_test3(){
    18 
    19     Log.e(TAG_OPERATOR,"____op_test3___")
    20 
    21     var op3 = OP3()
    22     Log.e(TAG_OPERATOR,"op3 = $op3")
    23 
    24     var ret = op3 + 5
    25     Log.e(TAG_OPERATOR,"op3 + 5 = $ret")
    26 
    27     var op4 = OP3(100)
    28     Log.e(TAG_OPERATOR,"op4 = $op4")
    29 
    30     ret = op3 + op4
    31     Log.e(TAG_OPERATOR,"op3 + op4 = $ret")
    32 
    33 }

      结果

    2019-09-05 19:44:43.451 19781-19781/com.example.kotlin E/operator: ____op_test3___
    2019-09-05 19:44:43.452 19781-19781/com.example.kotlin E/operator: op3 = 0
    2019-09-05 19:44:43.452 19781-19781/com.example.kotlin E/operator: op3 + 5 = 5
    2019-09-05 19:44:43.452 19781-19781/com.example.kotlin E/operator: op4 = 100
    2019-09-05 19:44:43.452 19781-19781/com.example.kotlin E/operator: op3 + op4 = 100

    3.扩展属性

    • 扩展属性允许定义在类或者kotlin文件中,不允许定义在函数中。
    • 扩展可属性 没有幕后字段(backing field),不允许被初始化,只能由显式提供的 getter/setter 定义
    • 可以扩展一个val,也可以扩展一个var

    3.1 扩展一个不可修改属性 val

     1 class C10{
     2     fun f10(){
     3     }
     4 }
     5 
     6 //给C10 扩展一个不可修改的属性
     7 val C10.SIZE : Int get()  = 10
     8 
     9 fun test10(){
    10     var c10 = C10();
    11     Log.e(TAG_EXTENSIONS,"c10.SIZE = ${c10.SIZE} ")
    12 }

      结果

    2019-09-05 22:21:39.074 22680-22680/com.example.kotlin E/extensions: c10.SIZE = 10 

    3.2 扩展一个可以修改的属性 var

     1 //11.给C11 扩展一个可修改的属性
     2 
     3 class C11
     4 
     5 internal var c11_num = 20
     6 
     7 var C11.num : Int
     8     get() {
     9         return c11_num
    10     }
    11     set(value) {
    12         c11_num = value
    13     }
    14 fun test11(){
    15     var c11 = C11();
    16     var num = c11.num;
    17 
    18     c11.num = 20 * 2
    19 
    20     Log.e(TAG_EXTENSIONS,"c10.num = ${c11.num} , num = $num ")
    21 }

      结果

    2019-09-05 22:21:39.075 22680-22680/com.example.kotlin E/extensions: c10.num = 40 , num = 20 

    3.3 给Any扩展一个Context

     1 val Any.HEIGHT: Int
     2     get() {
     3         return 33
     4     }
     5 
     6 class STU
     7 val stu = STU()
     8 
     9 val Any.ex_stu : STU   //ex_stu不可变,但是它的成员可以变化
    10     get() {
    11         return stu
    12     }
    13 
    14 lateinit var g_context : Context
    15 
    16 var Any.ex_context : Context
    17     get() {
    18         return g_context
    19     }
    20     set(value) {
    21     }

      1.在application的oncreate中初始化  g_context

      2.在没有context的类中使用context

     1 class LogUtil {
     2     companion object {
     3         ...
     4 
     5         fun startLog(){
     6             val LOG_FILE = ex_context.getExternalFilesDir("logs").toString() + "/xxx.log"
     7             try {
     8                 fileWriter = FileWriter(LOG_FILE,false)
     9                 initLogThread()
    10             }catch (e : Exception){
    11             }
    12         }
    13     }
        //...
    14 }

    4.扩展在类内部

      扩展放在类内。不用继承,不用生成对象,就可以访问另一个类的成员 。

     1 fun test13(){
     2     //不用继承,不用生成对象,就可以访问另一个类的成员
     3     data class A(var name : String,var age : Int){
     4         fun id() = 1
     5         fun name() = "nik"
     6     }
     7     data class B(var id : Int) {
     8         fun A.fid(){
     9             var id = id()
    10         }
    11         fun A.fn(){
    12             var name = name()
    13         }
    14     }
    15 }
  • 相关阅读:
    面试8:找二叉树的下个结点
    面试8:找二叉树的下个结点
    面试题7:重建二叉树
    面试题7:重建二叉树
    Kenneth A.Lambert著的数据结构(用python语言描述)的第一章课后编程答案
    基础的Mapgis三维二次开发-插件式
    面试题6:从尾到头打印链表
    C语言中声明和定义详解(待看。。
    面试题5:替换空格
    面试题5:替换空格
  • 原文地址:https://www.cnblogs.com/mhbs/p/11470446.html
Copyright © 2020-2023  润新知