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 }

 

posted @ 2019-09-05 23:05  f9q  阅读(363)  评论(0编辑  收藏  举报