expand

1. Extend the original sound API

To declare a function extension, we need to prefix the function with a receiver type. Next we
will add a swap function to MutableList:

// 扩展:为类添加成员函数和属性
fun MutableList<Int>.swap(index1:Int, index2:Int)
{
    val tmp = this[index1]
    this[index1] = this[index2]
    this[index2] = tmp
}
fun ArrayList<Int>.swap(index1:Int, index2:Int)
{
    val tmp = this[index1]
    this[index1] = this[index2]
    this[index2] = tmp
}
fun main(args: Array<String>)
{
    var mulableList = mutableListOf(1,2,3,4,5)
    mulableList.swap(0,2)
    println(mulableList)

    var list:ArrayList<Int> = ArrayList()
    list.add(20)
    list.add(30)
    list.add(40)
    list.swap(0,2)
    println(list)
}

The this keyword in the extension function corresponds to the receiver object. Now we can
use this function on any MutableList instance

2. Extend the custom class

//  扩展自定义类
//  通过扩展在顶层添加的成员函数和属性无法在子类中重写,因为没有办法加open
open class MyParent(val value1:Int, val value2:Int)
{
    var mValue1: Int = value1
    var mValue2: Int = value2
    fun add():Int
    {
        return mValue1 + mValue2
    }
}
class MyChild(value1:Int, value2:Int):MyParent(value1, value2)
{
    fun sub():Int
    {
        return mValue1 - mValue2
    }
}
//  通过扩展向MyParent类添加一个printResult方法
fun MyParent.printResult()
{
    println("${mValue1} + ${mValue2} = ${add()}")
}
//  通过扩展向MyChild类添加一个printResult方法
fun MyChild.printResult()
{
    println("${mValue1} - ${mValue2} = ${sub()}")
}
fun main(args: Array<String>)
{
    var parent1: MyParent = MyParent(1,3)
    var parent2: MyParent = MyChild(1,3)
    var parent3: MyChild = MyChild(1,3)
    parent1.printResult()
    parent2.printResult()
    parent3.printResult()
}

Output result:

1 + 3 = 4

1 + 3 = 4

1 - 3 = -2

3. Solution to member function conflict

If a member function added to a class by extension has exactly the same structure as the original member function in the class, the internal member function takes precedence

//  成员函数冲突的解决方案
//  如果发生冲突,在类中定义的函数优先级高
class MyClass
{
    private var strValue:String = ""
    constructor()
    {

    }
    private constructor(str:String)
    {
        strValue = str
    }

    override fun toString(): String {
        return strValue
    }
    fun newInstance(value:Int):MyClass
    {
        return MyClass("内部成员函数")
    }
}
fun MyClass.newInstance(value:Int):MyClass
{
    return MyClass()
}
fun main(args: Array<String>)
{
    println(MyClass().newInstance(20))
}

output:

Internal member function

4. Extended properties

Similar to functions, Kotlin also supports property expansion:

val <T> List<T>.lastIndex: Int
get() = size-1

Note that since extensions don't actually add member properties to the class, there is no way for extension properties to have
a backing field. This is why initializers are not allowed to have extension properties. Extended properties can only be defined by
explicitly providing getter and setter methods. Initialization needs to use the backing field, that is, the field field, which can save the property to the field, or get the property value from the field

//  扩展属性

//  通过扩展添加的属性,不能使用field
class TestClass
{
    var mValue:Int = 0
    //  内部属性
    var str:String = ""
      get() = field  // backing field字段
      set(value)
      {
          field = value
      }
}
var TestClass.value:Int
    get() = mValue
    set(value)
    {
        mValue = value
    }
fun main(args: Array<String>)
{
    var testClass = TestClass()
    testClass.str = "hello"
    testClass.value = 1000
    println(testClass.str)
    println(testClass.value)
}

5. Extended Scope

Most of the time we define extensions at the top level, just below the package:

package foo.bar
fun Baz.goo() { ... }

In order to use this extension outside of the declared package, we need to import it when importing:

package com.example,usage
import foo.bar.goo // 导入所有名字叫 "goo" 的扩展
// 或者
import foo.bar.* // 导入foo.bar包下得所有数据
fun usage(baz: Baz) {
baz.goo()
}

6. Extensions in classes

The previous extensions are written at the top level, in fact, the extension can also be written in the class definition

//  在类中使用扩展
class D
{
    fun bar()
    {
        println("D.bar")
    }
}
class C
{
    fun baz()
    {
        println("C.bar")
    }
    //  在C类中扩展D类
    fun D.foo()
    {
        bar()    //  调用D类的bar方法
        baz()    //  调用C类的baz方法
    }
    fun caller(d:D)
    {
        d.foo()    // 调用扩展方法foo
    }
}
fun main(args: Array<String>)
{
    C().caller(D())
}

output:

D.bar

C.bar

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325645980&siteId=291194637