Kotlin 擴展

1.官方文檔

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

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

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 }

   結果this

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 }

  結果spa

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 }

  結果.net

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 }

  結果code

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 }

  結果htm

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 接口支持擴展函數

  可是接口實現者不用實現擴展的函數blog

 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 

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 }
相關文章
相關標籤/搜索