kotlin extension method, properties

1. Concept

kotlin support without modifying the class code, class dynamically add attributes (extended attributes) and methods (extension method).

2. Extension Methods

Extended analytical method for performing static (compile-time), members of the analytical method performs dynamic (run-time).

(1) syntax

Definition of a function to add the "class name." Function is defined in the front, that is, the function expansion method corresponding to the class name of the class.

fun main(args: Array<String>) {
    val extensionClass = ExtensionClass()
    //调用拓展方法
    extensionClass.test()
}
//定义一个空类
class ExtensionClass
//为该空类定义一个拓展方法test()方法
fun ExtensionClass.test() = println("我是ExtensionClass的拓展方法")

(2) members of the priority method

If the extension method is extended class with members of the class method name and parameters, like , when the class object calls this method, the call will be members of the method.

fun main(args: Array<String>) {
    val extension = ExtensionTest()
    //此处调用的会是成员方法
    extension.test()
}

class ExtensionTest {
    fun test() = print("成员方法")
}
//该方法不会被调用
fun ExtensionTest.test() = println("扩展方法")

(3) is added to expand the system class method (for example as a String)

fun main(args: Array<String>) {
    val str = "123456"
    //调用String的拓展方法
    println(str.lastIndex())
}
//为String定义一个拓展方法
fun String.lastIndex() = length - 1

(4) extended the principle to achieve

java is a static language, you can not dynamically add methods, properties, class, unless the class to modify the source code and recompile the class.

kotlin extended attributes, it appears to be dynamically added to the class members when the method does not actually modify the extended class, kotlin essence is the definition of a function , when the object is extended class call extension methods, kotlin performs static resolution , calls the static function resolved to extend the function call.

Static resolution : according to the calling object, method name to find the expand function, converted into function calls.

As (2) str.lastIndex () method performs the process of:
① Check str type (Find a String);

② Check whether the String defined lastIndex () member method, if defined, the compiler directly;

③ If String is not defined lastIndex () method, kotlin Find program is promising String class extends lastIndex () method (that is, whether there is fun String.lastIndex ()), if the extension method definition, will execute the extension method ;

④ neither defined lastIndex () member method did not define an extension method, the compiler does not pass naturally.

(5) extension method static resolution calling attention to points

Because the static call the extension method is performed at compile time, so if the parent and child classes are an extension method extends the same name, the type of citations are under the parent class, calls the extension method of the parent class.

/**
 * 拓展属性、方法
 */
fun main(args: Array<String>) {
    val father : ExtensionTest = ExtensionTest()
    father.test()//调用父类扩展方法
    val child1 : ExtensionTest = ExtensionSubTest()
    child1.test()//引用类型为父类类型,编译时静态调用的还是父类的扩展方法
    val child2 : ExtensionSubTest = ExtensionSubTest()
    child2.test()//此时才是调用子类的扩展方法
}

/**
 * 父类
 */
open class ExtensionTest

/**
 * 子类
 */
class ExtensionSubTest : ExtensionTest()

/**
 * 父类扩展一个test方法
 */
fun ExtensionTest.test() = println("父类扩展方法")

/**
 * 子类扩展一个test方法
 */
fun ExtensionSubTest.test() = println("子类扩展方法")

(6) The method of nullable type extension (equals method to expand Example)

kotlin allow expansion nullable type extended method such, the null method can be invoked.

fun main(args: Array<String>) {
    val a: Any? = null
    val b: Any? = null
    println(a.equals(b))
}

fun Any?.equals(any: Any?): Boolean = this != null && any != null && any.equals(this)

3. Extended Attributes

(1) concept

kotlin extended attribute allows dynamic class, by adding extended attribute get, set-implemented method, not behind the field (filed).

Extended attributes did not really add a property to the class, the class can only be described as calculated by the get, set out the method attribute.

Limit: ① expansion property can not have an initial value; ② extended attribute field behind the access not filed with the keyword; ③val get methods must provide, var must provide get and set methods.

(2) define the extended attribute

fun main(args: Array<String>) {
    val extensionTest = ExtensionTest("a", "b")
    println(extensionTest.param1)//a
    println(extensionTest.param2)//b
    println(extensionTest.extensionParam)//a-b
}

/**
 * 定义一个类,包含属性param1、属性param2
 */
class ExtensionTest(var param1: String, var param2: String)

/**
 * 为该类扩展属性extensionParam
 */
var ExtensionTest.extensionParam: String
    set(value) {
        param1 = "param1$value"
        param1 = "param2$value"
    }
    get() = "$param1-$param2"

4. manner defined in class members extend

Other methods for the extended class definitions, attributes, the extended method, can be extended by a class in the class in which a class object call extension methods.

Extended to define the class members, belonging to the class is extended, thus calling class members are extended extension method directly (this can be omitted), and because it is located where the class, so they can directly call the members of the class where .

fun main(args: Array<String>) {
    val extensionTest = ExtensionTest()
    val extensionTest2 = ExtensionTest2()
    extensionTest2.info(extensionTest)
}

/**
 * 定义一个类包含test方法
 */
class ExtensionTest {
    fun test() = println("ExtensionTest的test方法")
}

/**
 * 定义一个类包含test方法,包含ExtensionTest的一个扩展方法
 */
class ExtensionTest2 {
    val a = "a"
    fun test() = println("ExtensionTest2的test方法")
    fun ExtensionTest.func() {
        println(a)//调用扩展类的成员
        test()//调用被扩展类的成员,相当于this.test()
        [email protected]()//同名的需要用this@类名的方式来调用
    }

    fun info(extensionTest: ExtensionTest) {
        extensionTest.func()
    }
}

The band spread function anonymous recipients

(1) concept

Extension Method (. Fun method name class name ()) to remove the anonymous method name is called spread function with the receiver, the receiver is class itself , shaped like: fun Int ():. Int .

fun main(args: Array<String>) {
    val extensionTest = ExtensionTest()
    println(extensionTest.noNameExtensionFun("向带接收者的匿名函数传入的参数"))//使用匿名扩展函数
}

/**
 * 定义一个空类
 */
class ExtensionTest

/**
 * 为空类定义一个带接收者的匿名扩展函数
 */
var noNameExtensionFun = fun ExtensionTest.(param: String): String {
    println(param)
    return "我是来自带接收者的匿名扩展函数的返回值"
}

(2) Function type spread function with anonymous recipients

With normal function, anonymous extension method also has the function type, function types (1) as: ExtensionTest (String) -> String.

Anonymous extension functions and lambda expressions (3) with the recipient

If the receiver can be inferred from the context type, a lambda expression can be used

fun main(args: Array<String>) {
    test {
        println(it)
        "匿名扩展函数返回值"
    }
}

/**
 * 定义一个空类
 */
class ExtensionTest

/**
 * 定义一个函数,形参为ExtensionTest.(String) -> String类型,相当于同时为ExtensionTest类扩展了一个匿名扩展函数
 */
fun test(fn: ExtensionTest.(String) -> String) {
    val extensionTest = ExtensionTest()
    println("调用匿名扩展函数:${extensionTest.fn("匿名扩展函数传入形参")}")
}

6. extended usage scenarios

Expand greatly increasing the flexibility of the program, java if you want to extend some of the properties of a class must be achieved by means such as inheritance, kotlin directly using the syntax can be dynamically expanded it easier to organize some tools methods.

fun main(args: Array<String>) {
    "打印日志".log()
}

/**
 * 为String字符串添加一个打印日志的扩展方法
 */
fun String.log() {
    println(this)
}

Guess you like

Origin www.cnblogs.com/nicolas2019/p/10932131.html