[Kotlin beginner] extension - enjoy programming

About the author: CSDN blog expert, Huawei cloud · cloud sharing expert certification

Series column: Kotlin beginner

Learning and communication: three people must have my teacher; Choose the good and follow it, and change the bad.

catalogue

1, Introduction

2, Extension function

2.1 defining extension functions

2.1. 4 define the superclass (Any) extension function

2.1. 5 generic extension function

3, Extended properties

4, Controllable class extension

5, Define extension file

5.1 definition extension file

5.2 use

5.3 rename extension (import file alias)

6, () - > unit and reference type ()->Unit

1, Introduction

Kotlin can extend the properties and functions of a class without inheriting or using the Decorator pattern.

Extension is a static behavior that does not affect the extended class code itself.

2, Extension function

Extension functions can add new functions to existing classes without modifying the original class.

2.1 defining extension functions

Extensions can be used for custom classes, such as List, String, and other classes in the Kotlin standard library. Similar to inheritance, extension can also share class behavior. When you can't contact a class definition or a class doesn't use the open modifier, so you can't inherit it, extension is the best choice to add class functions.

//Defines the extension function of the School class
fun School.student():String{
    return "$name-Learning knowledge"
}
  • School: represents the receiver of the function, that is, the object of the function extension

  • student: name of extension function

  • String: return type ("$name - learn knowledge")

Others are similar to defining general functions.

2.1. 1. Define the School class

class School(var name:String){
    //Self contained function
    fun teacher():String{
        return "$name-Teaching and educating people"
    }
}

2.1. 2 extension function

//Defines the extension function of the School class
fun School.student():String{
    return "$name-Learning knowledge"
}
//Defines the extension function of the String class
fun String.addSC():String{
    return "$this-Shuai Ci"
}

fun main() {
    //Original function of School class
    println(School("Super Seminary").teacher())//Super seminary - teaching and educating people
    //Extension function of School class
    println(School("Super Seminary").student())//Super seminary - learning knowledge
    //Extension function of String class
    println("Kotlin".addSC())//Kotlin shuaizi
}

2.1. 3. Extended function support range

After the extension function is defined, it can be called directly under the same package, and the defined extension function needs to be imported under other packages. The extension functions defined under the extension package are used in the classkotlin package.

Extension functions with the same name cannot be defined in the same package.

import com.scc.kotlin.primary.extension.School
import com.scc.kotlin.primary.extension.addSC
import com.scc.kotlin.primary.extension.student
fun main() {
    println(School("Class Bao Xia").student())//Class package - learning knowledge
    println("ClassKotlin".addSC())//ClassKotlin Shuai Ci
}

Define the extension function addSC() under multiple packages. When calling:

2.1. 4 define the superclass (Any) extension function

Because Any is a superclass, its extension function can also be used directly by other classes. This function is really powerful.

//Define Any extension function
fun Any.eat(): Any {
    return this
}
fun main() {
    //Because Any is a superclass, its extension function can also be used directly by other classes
    println("Superclass".eat())//Superclass
    println(15.eat())//15
}

Superclass eat().addSC() error

    //An error is reported because the addSC() function is an extension function of the String class, and the Any class cannot be called directly
    //Unless "superclass" is used The return type of eat() Any is changed to String and then called.
    "Superclass".eat().addSC()

It's time to introduce generic extension functions.

2.1. 5 generic extension function

The new generic extension function can not only support any type of receiver, but also retain the type information of the receiver. After using generic types, the extension function can support more types of receivers and has a wider scope of application.

//Defining generic extension functions
fun <T> T.scww():T{
    return this
}
fun main() {
    //WaKa calls the generic extension function scww(), returns the String type, and calls the String type extension function addSC()
    println("WaKa".scww().addSC())//WaKa shuaizi
    //Int type 15 calls the generic extension function scww(), and returns int type to call the apply {} function
    println(15.scww().apply { })//15
}
  • String type WaKa calls the generic extension function scww(), returns string type and calls the string type extension function addSC()

  • Int type 15 calls the generic extension function scww(), and returns int type to call the apply {} function

Generic extension functions can be seen everywhere in the Kotlin standard library, such as the apply function. The apply function is defined as a generic extension function, so it can support any type.

public inline fun <T> T.apply(block: T.() -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block()
    return this
}

3, Extended properties

In addition to adding function extension functions to classes, you can also define extension properties for classes.

Extended attributes can be defined in classes or kotlin files, but not in functions. Initialization property is not allowed to be initialized because it has no back-end field. It can only be defined by explicitly provided getters / setters.

Extended properties can only be declared as val.

//Define extended properties
//Add an extended attribute to the String class, which can count the character length and add 10.
val String.lengthSc
    get() = this.length.plus(10)

//Add a position attribute to the School class
val School.position
    get() = "${name}-Senior high school"
    
fun main() {    
    println("One, two, three, four, five, go up the mountain to fight the tiger".lengthSc)//21
    println(School("Xinguan middle school").position)//Xinguan middle school - Senior High School
}

4, Controllable class extension

You can also define extension functions for nullable types. By defining extension functions on nullable types, you can directly solve the possible null value problem in the extension function body.

//Nullable class extension
//When String is null, print all blank - default
fun String?.nullWithDefault(default: String) {
    println(this ?: "are void-$default")
}
//When School is null, print default - the School is gone
fun School?.dropOut(default: String) {
    println(this ?: "$default-The school is gone")
}

fun main() {
    var str: String? = null
    str.nullWithDefault("empty")//Everything is empty - empty

    str = "Data has arrived"
    str.nullWithDefault("empty")//Data has arrived

    var school: School? = null
    school.dropOut("No name")//No name. - the school is gone

    school = School("Shuaici College")
    school.dropOut("Default drop out")//com.scc.kotlin.primary.extension.School@19dfb72a
}

infix keyword

The infix keyword is applicable to extensions and class functions with a single parameter. It allows you to call functions in a more concise syntax. If a function definition uses the infix keyword, the point operation between the receiver and the function and a pair of parentheses of the parameter can be omitted when calling it. (similar to the to function)

//infix keyword
infix fun String?.nullInfixDefault(default: String){
    println(this ?: "Infix-$default")
}
fun main() {
    str = null
    str nullInfixDefault "Null value"   //Infix null
    str = "Not empty"
    str nullInfixDefault "Null value"  //Not empty
    //This is similar to mapOf
    mapOf("Key" to "Value")
}

to function source code

Generic extension function, prefixed with infix keyword

public infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that)

Extension functions in the Kotlin standard library: many functions provided by the Kotlin standard library are realized through extension functions and extension attributes. Standard library files containing class extensions are usually named after the class name plus the s suffix, such as sequences kt,Ranges.kt,Maps.kt.

5, Define extension file

The extension function needs to be used in multiple files. It can be defined in a separate file and then import ed.

5.1 definition extension file

package com.scc.kotlin.primary.extension

//Define extension file
fun <T> T.scFile(): T {
    println("come from ScFile Greetings from")
    return this
}

5.2 use

scFile() is called for files under the same package name:

fun main() {
    str.scFile()//Greetings from ScFile
}

scFile() is called for files under other packages:

import com.scc.kotlin.primary.extension.scFile
fun main() {
    var userInfo4 = UserInfo4()
    userInfo4.scFile()//Greetings from ScFile
}

5.3 rename extension (import file alias)

import com.scc.kotlin.primary.extension.scFile as scAliasFile

fun main() {
    var userInfo4 = UserInfo4()
    userInfo4.scAliasFile()//Greetings from ScFile using the newly defined alias
//    userInfo4.scFile() / / unable to use. An error is reported
}

6, () - > unit and reference type ()->Unit

package com.scc.kotlin.primary.extension

//() - > Unit: ordinary anonymous function
fun String.doAnonymous(anonymous:() -> Unit):String{
    anonymous()
    return "$this,AnonymousN"
}
//String. () - > Unit: this in the anonymous function points to a string object, which is called implicitly
fun String.doAnonymousString(anonymous: String.() -> Unit) :String{
    println(this)
    anonymous()
    return this
}
//The generic anonymous function used here uses its internal this
fun <T> T.doAnonymousT(anonymous: T.() -> Unit):T {
    println(this)
    anonymous()
    return this
}
fun main() {
    //Ordinary anonymous function
    "a".doAnonymous{
//println("$this, check") / / if this is used here, an error will be reported
    }

    //this inside the anonymous function points to a String object
    "b".doAnonymousString{
        println("$this,have a look")
    }
    15.doAnonymousT {
        println("$this,How lonely invincible is")
    }
}

DSL

Using this programming paradigm, you can write the industry-famous "domain specific language" (DSL), an API programming paradigm, which exposes the functions and characteristics of the receiver, so that you can use the lambda expressions you define to read and configure them.

Keywords: Java Android kotlin

Added by gnunoob on Fri, 31 Dec 2021 01:45:48 +0200