Note: the current document is a summary of Kotlin’s self-study, if there is any ambiguous meaning, please advise, thank you: -).
Contents and Keywords: - Attribute - Getter & Setter Backscene field - Classification - Backscene Property - Non-compliant backscene field - compile-time constant (const) - Top layer, object expression/object declaration, no Setter, can be used for annotations - extended property - - Late attribute (lateInit) -var, no custom accessor, non-empty and cannot be a native type - Override attribute (open → override) - Entrusted property (link: https://www.kotlincn.net/docs/reference/delegated-properties.html# by attribute) - inline attribute - function/method - ordinary function variable function - - the number of arguments Infix function (infix) - extension function spending - higher-order functions spending spending - anonymous functions - an inline function inline function (https://www.kotlincn.net/docs/reference/inline-functions.html#) - Lambda functions - Lambda functions - Lambda deconstructionCopy the code
Property with Getter&Setter accessors
Non-null type attributes must be initialized in a class construct (except lateInit).
[open/override/const/lateinit] [< access modifier >] var/val < property name > [: < property type >] [= < default property value >] [< getter accessor for property >] // var/val exists [setter accessor for property >] // val does not exist, can only be initialized in the constructorCopy the code
1. Getters & Setters and background fieldsfield
-
The system automatically defines accessors unless custom;
-
Accessor access modifiers can be customized;
-
The behind-the-scenes fields are in the custom accessor and do not incur call overhead;
var param1 : String = "1" get() = this.toString() set(value) {setDataFromString(value) // Parse the String and assign values to other attributes field = value } val param2: Int = 4 get() = this.tostring ()Copy the code
2. Attribute classification
1. Behind-the-scenes properties (prerequisite – requirements do not fit the “implicit Behind-the-scenes Field” scheme)
Accessing private properties through default getters and setters is optimized so that no function call overhead is introduced.
private var _table: Map<String, Int>? = null // private attribute public val table: Map<String, Int> get() {if (_table == null) {_table = HashMap() // Type argument inferred} return _table? : throw AssertionError("Set to null by another thread") }Copy the code
2. Compile-time constants (const)
const val SUBSYSTEM_DEPRECATED: String = "This subsystem is deprecated"
Copy the code
-
The property is in the top layer or Object member;
-
Class using a String or other native type value;
-
There is no getter;
-
Can be used in annotations;
@deprecated (SUBSYSTEM_DEPRECATED) fun foo() {...... }Copy the code
3. Override attribute (Override)
- Inheritance (
override
Attribute from the base classopen
attribute - Can only use
var
coverval
, otherwise not, cannot repeat the statementsetter
Function.
4. Delay properties (LateInit)
- Do not want to initialize in a construct and want to avoid null checking;
- Requirements: must be mutable var, have no custom getters/setters, cannot be null, and cannot be a native type;
- Uninitialized access throws a fixed exception;
5. Extended properties – Specify type callable, statically like properties
val <T> List<T>.lastIndex: Int
get() = size - 1
Copy the code
-
Extended properties have no initializers and can only be provided by getters and setters
For example: val foo. bar:Int get() = 2 // Cannot use val foo. bar = 1Copy the code
-
Associated objects can also have extended attributes. Call method = (Java) Calls to static functions and properties
Class MyClass {companion object {} // will be called "companion"} fun myclass.panion.foo () {// Companion object functions //...... } val MyClass.Com panion. Bar: Int the get () = 2 / / associated MyClass object extension functions and attributes of call. The foo () MyClass. BarCopy the code
6. Delegate properties
Delegate the setter and getter of a property to set or get the value.
Grammar:
Var < attribute name >: < type > by < expression >Copy the code
Inline attribute
An inline property or its accessor uses an inline modifier to mark the accessor as an inline accessor, the same as an inline function.
Function/method
-
When a function is defined, the parameter representation is Pascal representation;
-
Unit can exist as a return type that does not need to be returned explicitly or at all;
-
The single-line function body may not be surrounded by “{}”, or the return value type may be omitted explicitly;
fun double(x: Int): Int = x * 2 fun double(x: Int) = x * 2 Copy the code
-
Functions can be nested within each other, and internal functions are called local functions.
-
Function overrides: subclasses override parent **open** functions must omit parameter defaults;
-
Functions can be written in attribute format, and their data types are related to the type of the passed argument and the type of the returned value, for example :(Int,String)->Boolean;
-
Functions can use generics;
Fun <T> singletonList(item: T): List<T> { }Copy the code
Common function
1. Variable function of parameter number (vararg
)
-
Definition:
java: public <T> List<T> listOf(T ... params){ //T ... params -> params[N] ... } kotlin: fun <T> listOf(vararg ts: T): List<T> { //ts is a Array //vararg = variable number of arguments ... } Copy the code
-
use
-
Pass in arguments of the same type or an array of arguments to consolidate into this array using the stretch operator *;
Val list = listOf(1,2,3) val list = listOf(*list,5,6,7,.....) // Integrate the contents of the list into list2.Copy the code
-
Infix function (infix
)
Using the **infix modifier, a member function or extension function with only one argument ** can be represented using infix notation.
Infix fun Int. SHL (x: Int): Int {... } // use val a = 1 //val b = a (0) val b = a (0Copy the code
Extension function
-
Specifies the type of function to be called. Specifies that the type can be null for null-handling. This inside the function calls the value of the function by default.
// The specified type can be empty fun Any? .swap(index1:Int,index2:Int){ if (this == null){ .... } } fun MutableList<Int>.swap(index1: Int, index2: Int) {val TMP = this[index1] this[index2] this[index2] = TMP} val l = mutableListOf(1, 2, 3) l.swp (0, 2) // "this" inside "swap()" gets the value of "l"Copy the code
-
Lower priority than ordinary functions of the same type;
-
Extension functions can also be overridden by inheriting open.
-
Extension functions are statically distributed, that is, they are not virtual methods based on the receiver type. This means that the extension function called is determined by the type of the expression on which the function is called, not by the result of the expression’s run-time evaluation.
open class D {} class D1 : D() {} open class C {//D and D1 are extension receiver open fun d.foo () {println(" d.foo in C")} open fun d1.foo () {println(" d1.foo in C")} // Call the extension function fun caller(d: d) {d.foo()} Override fun d.foo () {println(" d.foo in C1")} override fun d1.foo () {println(" d1.foo in C1")}} / / C and C1 to distribute the receiver (C). The caller (D ()) / / output "D.f oo in C" C1 (). Caller (D ()) / / output "D.f oo in C1" -- virtual parsing C () distribution of the receiver. Caller (D1 ()) / / output "D.foo in C" -- extends receiver static resolutionCopy the code
-
The class object of the extension function is called the distribution receiver, virtual resolution;
-
The specified class object of the extension function is called the extension receiver and is resolved statically;
-
-
An associated object can also have extension functions that are called directly using the class name as a qualifier.
Class MyClass {companion object {} // will be called "companion"} fun myclass.panion.foo () {//...... } // call myclass.foo ()Copy the code
Higher-order functions
-
Definition:
-
Functions called by higher-order functions (Lambda functions or anonymous functions) can access/change variables in the closure (outer scope)
-
Inside a higher-order function, you can use the referenced function with the function return value name +”()” and use the higher-order function internal arguments.
-
Advantages: Reduced function definition and function nesting, not affected by generic type judgment;
-
Disadvantages: Multiple writing of anonymous functions causes code redundancy.
Compare () fun compare(a: String, b: String): Boolean{return a.length < B.length} fun Max (collection: Collection<String>): String? { var max: String? = null for (it in collection) if (max == null || compare(max, It)) Max = it return Max} left left left left left left left left left left down down down down down down down down down left left left left left left left left left left down down down down down down down down down left left left after change left left left left left down down down down down down down left left left left left left left left left left down down down down down down down down down left left left left left left left/left/down down down down down down down down the compare () returns a value to a Boolean, you can reference function Max () : Fun compare(a: String, b: String): Boolean = a.length < b.length //Lambda high order function fun <T> Max (collection: Collection<T>, less: (T, T) -> Boolean): T? { var max: T? = null for (it in collection) if (max == null || less(max, It)) Max = it return Max} left left left left left left left left left down down down down down down down down left left left left left left left left left left down down down down down down down down down left left left left continue to simplify left left left left down down down down down down down left left left left left left left left left left down down down down down down down down down left left left left left left left left left fun down down down down down down down down down < T > compare (a: T, b: T) : Boolean{//return a.length < b.Length restricted by function parameter type return true... } //Lambda high order function fun <T> Max (collection: collection <T>, less: (T, T) -> Boolean): T? { var max: T? = null for (it in collection) if (max == null || less(max, Max (strings, {a, b -> a.length < b.length}) {if (string, b -> a.length < b.length})Copy the code
-
-
use
-
To call a member function, use :: with the function name;
fun toBeSynchronized() = sharedResource.operation() val result = lock(lock, ::toBeSynchronized) Copy the code
-
Incoming Lambda expression
lock(lock,{sharedResource -> sharedResource.operation()}) max(strings, { a, b -> a.length < b.length }) Copy the code
-
And you can do the same thing when the last argument is a function
lock(lock) {sharedResource -> sharedResource.operation()} max(strings) {a, b -> a.length < b.length } Copy the code
-
Use “_” when passing arguments in Lambda expressions but not using them
map.forEach { _, value -> println("$value!") } Copy the code
-
Higher-order functions have only one function argument, and the parentheses in the call can be completely omitted.
val doubled = ints.map { value -> value * 2 } Copy the code
-
If a higher-order function has only one argument and the argument has only one argument, omit the declaration and ->, and use only the IT field:
val doubled = ints.map { it * 2 } Copy the code
-
Anonymous functions
Fun [< specify receives (call) type >.] (< parameter name > 1: < type >, < 2 > parameter name: < type >,...). : > < return value type} {/ / function body fun [< specify receives (call) type >.] (< parameter name > 1: < type >, < parameter name > 2: < type >,...). :< return value type > = < short function body >Copy the code
Inline functions (deformation of higher-order functions)
When higher-order functions are used, each function is referred to as an object, which generates a closure, and variables can be accessed from within the called function. Memory allocation and virtual invocation of variables introduce runtime overhead.
An inline function
-
The overhead can be eliminated by inlining Lambda function expressions. The compiler does not create a function object for the argument and generate a call. Use the inline modifier to mark the function to inline the Lambda function expression, that is, to the call.
-
Inlining can lead to an increase in generated code, but if we use it properly (without inlining large functions), it can improve performance, especially at “megamorphic” calls in loops.
Inline fun lock<T>(lock: lock, body: () -> T): T {//...... }Copy the code
Prohibit inline
-
The noinline modifier is used when a higher-order function passes multiple function arguments and only some do not want to be inline.
-
Warning is generated when there is no inline argument function in an inline function.
-
A naked return inside a Lambda expression is not allowed unless the function passed by the Lambda expression is inline, in which case the return is called a nonlocal return.
Fun foo() {ordinaryFunction {return error: Fun foo() {inlineFunction {return // OK: foo() {return: foo() {return: foo() {return: foo() {return: foo() {return: foo(); The lambda expression is inline}}Copy the code
-
Some inline functions may call lambda expression arguments that are passed to them not directly from the function body, but from another execution context, such as local objects or nested functions. In this case, non-local control flow is also not allowed in the lambda expression. To identify this, the lambda expression argument needs to be marked with the Crossinline modifier:
Inline fun f(Crossinline body: () -> Unit) {val f = object: Runnable {override fun run() = body()} //... }Copy the code
Externalized type parameters
Lambda function expression
1. Lambda function expressions
Functions that return values can be expressed as Lambda expressions to be used by higher-order functions.
In higher-order functions, functions referred to as arguments are represented as attributes.
Example 1:
fun <T> max(collection: Collection<T>, less: (T, T) -> Boolean): T? { var max: T? = null for it in the collection) if (Max = = null | | less (Max, it)) Max = it return Max} / / function: fun less (x: Int, y: Int) : Boolean {return x < y} left left left left left left left left left left left left down down down down down down down down down left deformation left left left left left left left left left down down down down down down down down left left left left left left left left left fun down down down down down down down down down less (x: Int, y: Int) : Boolean = x < y left left left left left left left left left left down down down down down down down down down left left left anonymous left left left left left left left left down down down down down down down down left left left left left left left left left left down down down down down down down down down {x: Int, y: Int - > x < y} left left left left left left left left left left left left down down down down down down down down down left to do parameter left left left left left left left down down down down down down down left left left left left left left left left val down down down down down down down down down less = {x: Int, y: Int - > x < y} left left left left left left left left left left left left down down down down down down down down down left lift type left left left left left left left down down down down down down down left left left left left left left left left val down down down down down down down down down less: (Int, Int) - > Boolean = {x, y - > x < y}Copy the code
Higher-order functions have only one function argument. You can omit the “()” wrapper for the function argument.
Example 2(reverse disassembly):
Ints. Filter {val shouldFilter = > 0 / it/using it and the single parameter, you can directly see that is the function shouldFilter} left left left left left left left left left left down down down down down down down down down left left left + type left left left left left down down down down down down down left left left left left left left left left left left down down down down down down down down down Ints.filter {val shouldFilter:(Int) -> Boolean = it > 0 return@filter shouldFilter} ↓↓↓↓↓↓↓↓↓↓↓↓↓ ↓ Lambda Ints. Filter {val shouldFilter:(Int) -> Boolean ={it -> it > 0} return@filter shouldFilter} Left left left left left left left left left left down down down down down down down down down left left left to change function left left left left left down down down down down down down left left left left left left left left left left down down down down down down down down down left ints. Filter {/ / current higher-order functions only one parameter fun shouldFilter (it: Int) : Boolean {/ / internal function? Attribute within internal function return it > 0} return @ filter shouldFilter} left left left left left left left left left left left left down down down down down down down down down left function reduction left left left left left left left down down down down down down down left left left left left left left left left fun down down down down down down down down down List < Int >. The filter ( method:(Int) -> Boolean ):Boolean{ .... }Copy the code
In a Lambda expression, a higher-order function whose arguments are not used can be named with “_”.
map.forEach { _, value -> println("$value!") }
Copy the code
2. Lambda deconstruction
You can use the destruct declaration syntax for lambda expression parameters. If lambda expressions have arguments of type Pair (or map.Entry or any other type with a corresponding componentN function), then multiple new arguments can be introduced in place of a single new argument by enclosing them in parentheses:
map.mapValues { entry -> "${entry.value}!" }
map.mapValues { (key, value) -> "$value!" }
Copy the code
Note the difference between declaring two parameters and declaring a destruct pair instead of a single parameter:
{a / / - >... } // a parameter {a, b //->...... } // Two parameters {(a, b) //->...... } // a pair of {(a, b), c //->... } // A deconstruction pair and other parametersCopy the code
If a component of the deconstructed argument is not used, it can be replaced with an underscore to avoid fabricating its name:
map.mapValues { (_, value) -> "$value!" }
Copy the code
You can specify the types of arguments for the entire deconstruction or specify the types of specific components separately:
map.mapValues { (_, value): Map.Entry<Int, String> -> "$value!" }
map.mapValues { (_, value: String) -> "$value!" }
Copy the code
This article is from Kotlin Language Center