Introduce a,

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

Extension is a static behavior that has no effect on the extended class code itself.

The first generation of mobile phones used to only make calls, the second generation expanded the function of listening to music, and the third generation and later mobile phones have the function of listening to music.

2. Extension functions

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

2.1 Define extension functions

Extensions can be used for custom classes, as well as for classes such as List, String, and other classes in the Kotlin library. Like inheritance, extensions share class behavior, and are the best way to add functionality to a class when you can’t touch a class definition, or when you can’t inherit a class because it doesn’t use the open modifier.

Funschool.student ():String{return "$name- learning knowledge "}Copy the code
  • School: represents the receiver of the function, which is the object to which the function extends
  • Student: Name of the extension function
  • String: Return type (“$name- learning knowledge “)

The rest is similar to defining a general function.

2.1.1 Defining the School class

Class School(var name:String){var teacher():String{return "$name- teaching "}}Copy the code

2.1.2 Extension functions

Funschool.student ():String{return "$name- learning knowledge "} funschool.addsc ():String{return "$this- handsome "} fun main() {println(School("超 教 师 ").teacher())//超 教 师 - teacherclass extension function Println ("Kotlin".addsc ())//Kotlin ("Kotlin".addsc ())}Copy the code

2.1.3 Extend the range of functions supported

Extension functions defined in the same package can be directly called, in other packages need to import defined extension functions. Extension functions defined under the Extension package, used in the ClassKotlin package.

Extension functions of 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. The extension. Student fun main () {println (School (" under Class package "). The student ()) / / Class under the package - learning knowledge Println (" ClassKotlin ". AddSC ()) / / ClassKotlin - handsome}Copy the code

Define the extension function addSC() under multiple packages, when called:

2.1.4 Defining the Superclass (Any) extension function

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

// Define the Any extension funany.eat (): Println (" superclass ".eat())// superclass println(15.eat())//15}Copy the code

“Superclass “.eat().addsc () error

The addSC() function is an extension of the String class. The Any class cannot be called directly unless the return type of.eat() is converted to String. "Super class". Eat (). AddSC ()Copy the code

This is the time to introduce generic extension functions.

2.1.5 Generic extension functions

The new generic extension functions not only support recipients of any type, but also retain the recipient type information. With the use of generic types, the extension functions can support more types of recipients, and the scope of application is much wider.

SCWW ():T{return this} fun main() {//WaKa calls SCWW (), Mandatory String Calling the String extension function addSC() println("WaKa".scww().addsc ())//WaKa- shuitimes //Int 15 Calling the generic extension function SCWW (), Println (15.scww().apply {})//15}Copy the code
  • WaKa of String calls the generic extension function SCWW (). AddSC () of String is returned.
  • Int 15 calls the generic extension SCWW () and returns Int to call apply{}

Generic extension functions are everywhere in the Kotlin library, such as apply, which 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
}
Copy the code

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 a class or kotlin file, not in a function. Since a property has no backing field, it is not allowed to be initialized and can only be defined by an explicitly supplied getter/setter.

An extended attribute can only be declared as val.

// Add an extension attribute to the String class. This extension attribute counts the length of characters and increments by 10. LengthSc get() = this.lengths.lengthsc get() = this.lengths.lengthsc get() = ${name}- lengthSc fun The main () {println (" 12345, went up into the mountain shoot tigers ". LengthSc) / / 21 println (School (" new crown high School "). The position) / / new champions league high School - high School}Copy the code

4. Controllable class extension

You can also define extension functions for nullable types, and by defining extension functions on nullable types, you can directly address null-value problems that may occur within the extension function itself.

// Nullable class extension // Print everything when String is null -default fun String? .nullWithDefault(default: String) { println(this ? } // When School is null, print default- School has no fun School? .dropOut(default: String) { println(this ? } fun main() {var STR: String? STR. NullWithDefault (" nullWithDefault ")// Var school: school? DropOut (" select school from school "); dropOut(" select school from school ") School dropOut (" default dropped out "). / / com. SCC kotlin. Primary. The extension. 19 dfb72a school @}Copy the code

Infix keyword

The infix keyword is suitable for extension and class functions that take a single argument. It allows you to call the function in a simpler syntax. If a function definition uses the infix keyword, it can be called without the dot operation between the receiver and the function and without the parentheses of the argument. (Similar to to function)

//infix keyword infix fun String? .nullInfixDefault(default: String){ println(this ? : "Infix-$default")} fun main() {STR = null STR nullInfixDefault "null" //Infix- null STR = "null" STR nullInfixDefault "null" MapOf ("Key" to "Value")}Copy the code

To function source

The generic extension function is preceded by the infix keyword

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

Extension functions in the Kotlin library: Many of the functions provided by the Kotlin library are implemented through extension functions and extension properties. Standard library files that contain class extensions are usually named after class names with an S suffix, such as Sequences. Kt, Ranges.

Define extension files

The extension function needs to be used in multiple files. You can define it in a separate file and then import it.

5.1 Defining extension Files

Package com. SCC. Kotlin. Primary. The extension / / define extension file fun < T > T.s cFile () : T {println (" greetings from ScFile ") return this}Copy the code

5.2 the use of

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

Fun main() {str.scfile ()// Greetings from scFile}Copy the code

Files under other packages call scFile() :

The import com. SCC. Kotlin. Primary. The extension. ScFile fun main () {var userInfo4 = userInfo4 () userInfo4. ScFile () / / greetings from scFile }Copy the code

5.3 Renaming an Extension (Import File Alias)

import com.scc.kotlin.primary.extension.scFile as scAliasFile fun main() { var userInfo4 = UserInfo4() Userinfo4.scaliasfile ()// Use the newly defined alias, greetings from ScFile // userInfo4.scfile ()// cannot use, error}Copy the code

()->Unit and reference type ()->Unit

Package com. SCC. Kotlin. Primary. The extension / / () - > Unit: Fun string.doanonymous (anonymous:) -> Unit):String{anonymous() return "$this,AnonymousN"} //String.() -> Unit: Inside the anonymous function this refers to a String object, implicitly calling fun String.doAnonymousString(anonymous: String.() -> Unit) :String{println(this) anonymous() return this} This fun <T> t. doanonymoust (anonymous: T.() -> Unit):T {println(this) anonymous() return this} fun main() {// Ordinary anonymous function "a".doanonymous {// Println ("$this, let's see ")// use this, DoAnonymousString {println("$this, look ")} 15. DoAnonymousT {println("$this, look ")} }Copy the code

DSL

Using such a programming paradigm, you can write the industry’s well-known Domain-specific language (DSL), an API programming paradigm that exposes the receiver’s functions and features so that you can read and configure them using lambda expressions you define.