Kotlin basic syntax

Kotlin is a statically typed programming language running on the Java virtual machine, known as the Swift of the Android world, designed and open sourced by JetBrains. Kotlin can be compiled to Java bytecode or JavaScript, making it easy to run on devices without a JVM.

A new object-oriented programming language is all of these things

1. Basic syntax includes package import type declaration keyword legal identifier... 2. Basic types 3. Conditional control 4. Loop control 5. The programming skills and ideas of object-oriented language are inseparable from abstraction. Encapsulation. Inheritance. PolymorphismCopy the code

The kotlin file ends with ==. Kt ==

Package declaration and guide package

// Pakage com.xx.xx improt Android. Content.ContextCopy the code

annotation

Kotlin is like Java // single-line comment /** * multi-line comment */Copy the code

Definitions of constants and variables

Var < identifier >: < type > = < initial value > var a: Int = 1 var conext: Context? Var b = 2.0f var c: Const const const const const const const const const const const const const const const const const const const const const const const const const const const const const const const const const const const const const const const const const const const const const const const const const const const Similar in Java public static final String TAG = "TAG" * * * * * * * * * * * * * * * * * * * * * * * a.k t file start * * * * * * * * * * * * * * * * * * * * * * * * const val TAG ="tag" // top-level object AA{const val MY_PI = 3.14159 fun print(s:String){log. e(tag,s)}} class BB{// Undeclared const val MY_PI = 3.14159 fun print(s:String){log. e(tag,s)}} class BB{// Undeclared const val MY_PI = 3.14159 Val xx xx} = * * * * * * * * * * * * * * * * * * * * * end of file a.k t * * * * * * * * * * * * * * * * * * * * * * * * *Copy the code

String template

Var a = 1 var s = "a is $a" var s = "a is $a" // result a is 1 "${function, expression}" var m = "${s.place ("is","value")} "// result a value 1Copy the code

Null check mechanism

var age:String? = "18" age = null var result = age!! .toint () var result = age? Var result: Int // result is a non-null type result = age? .toint () var result:Int? // result is nullable result = age? .toInt()Copy the code

The data type

Kotlin type Kotlin bits wide Java type Java wrapper types Java a wide
Double 64 double Double 64
Float 32 float Float 32
Long 64 long Long 64
Int 32 int Int 32
Short 16 short Short 16
Byte 8 byte Byte 8
Boolean true/ false Char kotlin = true/ false Char kotlin = true/ false Char kotlin = true/ false Char kotlin = true Kotlin first adds or subtracts the integer from the character encoding of the Char value, and then converts the calculation to the Char value. Subtracting two Char values: Kotlin returns an Int by subtracting the character encodings of the two Char values. Two Char values cannot be added. Var m:Char ='A' var n:Char ='B' val c=m+n val c=m+ n.toint () // Ok C =m+ n.toloat () // error val c= m-n // OK c is Int Each data type has the following methods, which can be converted to other types: toByte(): Byte toShort(): Short toInt(): Int toLong(): Long toFloat(): Float toDouble(): Double toChar(): Char // These methods are abstract methods of type Number, Double,Float, etcCopy the code

Type conversion

Kotlin requires explicit conversions between Float and Double, floating-point to integer, and integer to integer. When a value, variable, or constant of type Double or Float is converted to an integer, the fractional part of the floating-point value is truncated. When casting, try to cast to a wide range of data types, so that the program is more secure. Automatic promotion of expression types When an arithmetic expression contains more than one numeric value, the data type of the entire arithmetic expression is automatically promoted. All Byte and Short types are promoted to ints. The data type of the entire arithmetic expression is automatically promoted to the same type as the highest level operand in the expression. var b: Byte = 40 var c: Short = 97 var i: Int = 23 var d: Double = 0.314 val result = b + c + I * d Instanceof println(" ABC "is String) // true println(" ABC"! is String) // false println(null is Any) // fase println(null is Any?) // true "as" keyword forces class line conversion val manager = context.getSystemService(context.fingerprint_service) as FingerprintManagerCopy the code

Under controlled conditions

Var a = 10 var b = 20 val Max = if(a>b) a else b A: b 2. "when "(like Java switch case) var x :Int? =10 when(x){ 1->{ printf("x==1") } 2->{printf("x==2") } in 3.. 10 -> { } else->{ .... } } var a:Any? when(a){ is Boolean ->{ } is String ->{ } else -> { } }Copy the code

Kotlin cycle control

Note: Kotlin List, Map, and Set are prefixed to be Mutable. For example: Val a :MutableList<Int> = mutableListof(1,2,3) a. dd(4) List<Int> = listof(1,2,3) // The length must be 3. For (item in collection) print(item) if you want to iterate over an array or list by index val m:MutableList<Int> = mutableListOf(1,2,3,4) for (I in M.i ndices) {print (" I value -- - $I ${m} [I] ")} for (I in m. ithIndex ()) {print (" I value -- - $I ${m.g et ($} ")} by forEach loop {print(" $it ")} val m: HashMap<Int,Int>f = mapOf(1 to 1, 2 to 2, 3 to 3) Pair (3, 3)) for ((k, v) in m) {print (" -- - $$k v v k ")} m. orEach {k, v - > print (" -- - $$k v v k ")} normal cycle: the for (I in 1.. For (I in 4 downTo 1) print(I) // print(I) : "4321" also supports specifying the step size: for (I in 1.. For (I in 4 downTo 1 step 2) print(I) // Print (I) : For (I in 1 until 10) {// I in [1, 10), not including 10 println(I)}Copy the code

Kotlin

Functions in Kotlin are declared with the “fun” keyword

fun  add( x: Int , y: Int) : Int {
    return x+y
}
Copy the code

Parameters are specified in the < parameter name > : < type > format. Parameter types in functions must be specified

You can abbreviate it to a single expression function

fun add(x:Int, y: Int) = x + y 
Copy the code
Returns a function of Unit

If a function does not return any useful value, its return value is Unit, which does not need to be explicitly returned but can be omitted (like in Java ==void==).

fun printHello(str: String? ) : Unit { if(str! Else printlv(" STR is null ") return Unit} or fun printHello(STR: String?) { if(str! =null) println(str) else printlv("str is null ") //return Unit }Copy the code
Variable length parameter

The argument to a function (usually the last one) can be marked with the vararg modifier (similar to Java ==… = =)

Kotlin: fun printSome(vararg ints: Int) {ints.foreach (::println)} printSome(1,2,3,4,5) public void printSome( Int... ints){ ... }Copy the code
The default parameters

Function arguments can have default values, which are used when corresponding arguments are omitted. This reduces the number of overloads. Default values are defined by the = following the type and the given value.

fun reformat(str: String, normalizeCase: Boolean = true, upperCaseFirstLetter: Boolean = true, divideByCamelHumps: Boolean = false, wordSeparator: Char = ") {/*... // call reformat("ab_cd", false, false, true, "_") with the default argument // or more readable reformat("ab_cd", normalizeCase = false, upperCaseFirstLetter = false, divideByCamelHumps = true, WordSeparator = "_") // Reformat ("ab_cd", upperCaseFirstLetter =false) when I only need two arguments.Copy the code
Higher-order functions

Kotlin functions are all first-class citizens ==, which means == they can be stored in variables and data structures, passed as arguments to other higher-order functions, and returned == from other higher-order functions. Functions can be manipulated just like any other non-function value. To facilitate this, Kotlin, as a statically typed programming language, uses a series of == function types == to represent functions and provides a specific set of language constructs, such as lambda expressions. A higher-order function is a function that takes a function as an argument or return value

/ / function as a variable val aa: () - > Unit = {printf (" -- -- - > "aa)} val bb: () - > Unit = {printf (" - BBB - >")} / / anonymous functions as variable val aa6 = fun (x: Int, y: Int: Int {return x + y} val arry: ArrayList< ()->Unit > = arrayListOf(aa,bb)Copy the code
  • Function types
// Define a simple higher-order function: arguments of function type (of course you can have multiple arguments of function type) fun twoAndThree (operation: (Int, Int) -> Int) {val result = operation(2,3) // val result = operation.invoke(2,3) println("result is $result")} twoAndThree{ a,b -> a + b } // result is 5 twoAndThree{ a, B -> a * b} // result is 6 //operationCopy the code
  • Representation of a function type

    () -> Unit (

    () -> return ()

    (A) -> Unit

    (A,B) -> c

    A.(B)->C // Function types with receivers are similar to defining an extension function for type A

To specify a nullable function type, use parentheses :((Int, Int) -> Int)? .

Function types can be joined with parentheses :(Int) -> ((Int) -> Unit

Arrow notation is right associative, (Int) -> (Int) -> Unit is equivalent to the previous example, but not equal to (Int) -> Int) -> Unit.

  • Instantiation of a function type

1. Assign with Lambda expressions

var add1 : (Int, Int) -> Int = {a : Int, b : Int -> a + b}
Copy the code

2. Assign values using anonymous functions

var add2 : (Int, Int) -> Int = fun(x,y) :Int {
 return   x+y
}
Copy the code

3. Assist with declared functions

fun add(a:Int, b:Int) : Int ={return a+b} var add3: (Int, Int) -> Int = :: Add // If add is defined in class AA, then AA::add // If add is defined in a file, then ::add is fetchedCopy the code

4. Use function type variables

Var add4: (Int, Int) -> Int = {a: Int, b: Int -> a + b} var add4: (Int, Int) -> a + b} (Int, Int) -> Int = addCopy the code

5. Function type Derived class: A function type can be thought of as an interface. The class implements the interface and implements the specific function operations in the implementation class

class AddOperation : (Int, Int) -> Int{ override fun invoke(p1: Int, p2: Int): Int {return p1 + p2}} var add5: (Int, Int) -> Int = AddOperation()Copy the code
  • Call of a function type
  1. Invoke: This function can be invoked by a function type variable name. Invoke (parameter list);

  2. Direct call: You can also call the function directly from the function type variable name (argument list), using the variable name as the function name.

class

Classes can contain:

Constructor and initializer block function properties nested classes and inner class objects declare class inheritanceCopy the code
  • Class declaration

Kotlin declares that a class is declared by the ==class== keyword. A class declaration consists of the class name, the class header (specifying its type parameters, main constructor, and so on), and the body of the class surrounded by curly braces. Both the class header and the class body are optional; If a class does not have a class body, you can omit the curly braces.

The class Invoice {/ *... */ } calss EmptyCopy the code
  • The constructor

A class in Kotlin can have a primary constructor and one or more secondary constructors. The main constructor is part of the class header: it follows the class name (along with optional type arguments).

Class Person constructor(firstName: String) {/*... * /}Copy the code

The keyword ==constructor== can be omitted if the main constructor does not have any annotations or visibility modifiers

Class Person(firstName: String) {/*...... * /}Copy the code

The main constructor cannot contain any code. Initialization code can be placed in initializer blocks prefixed with the ==init== keyword.

During instance initialization, initialization blocks are executed in the order in which they appear in the class body:

class InitOrderDemo(name: String) { //1 val firstProperty = "First property: $name".also(::println) //2 init { println("First initializer block that prints ${name}") } //3 val secondProperty = "Second property: ${name.length}".also(::println) //4 init { println("Second initializer block that prints ${name.length}") } } Note: Different from Java static{} code blocksCopy the code

Declare attributes and initializations directly in the main constructor

Class Person(val firstName: String, val lastName: String, var age: Int) {/*... Class Person(a:String, b:String, c:Int){val firstName = a val lastName = b var age = c... }Copy the code

subconstructor

Classes can also declare subconstructors prefixed by ==constructor== :

class Person {
    var children: MutableList<Person> = mutableListOf<>()
    
    constructor(parent: Person) {
    
        parent.children.add(this)
        
    }
}
Copy the code

If a class has a primary constructor, each subconstructor needs to delegate to the primary constructor, either directly or indirectly through another subconstructor. Delegate to another constructor of the same class using the this keyword

Class Person(val name: String) {var children: MutableList<Person> = mutableListOf<>() constructor(name: String, parent: Person) : this(name) { parent.children.add(this) } }Copy the code

If a non-abstract class does not declare any (primary or secondary) constructors, it will have a generated primary constructor with no arguments. Constructor visibility is public. If you don’t want your class to have a public constructor, you need to declare an empty main constructor with non-default visibility:

Class private constructor () {/*... * /}Copy the code

There are four visibility modifiers in Kotlin: ==private==, ==protected==, ==internal==, and ==public==. If no modifiers are explicitly specified, the default visibility is public. Declared in a document:

Example. Kt package foo private fun baz() {... } class Bar {...... } var name = "TAG" public --> this means your declaration will be visible everywhere; Private --> It is only visible in the file in which it is declared; Internal --> It can be seen everywhere in the same module; (Module: a project, a set of Kotlin files compiled together) Protected --> not applicable to top-level declarations;Copy the code

Class declared in:

Open class Outer {private val a = 1 protected val b = 2 internal val c = 3 val d = 4 Nested {public val e: Int = 5}} private --> means only visible inside the class (containing all its members); Protected --> This class and visible in subclasses; Internal --> Any client in this module that can see the class declaration will see its internal members; Public --> Any client that can see the class declaration can see its public member;Copy the code

++ In Kotlin, external classes cannot access private members of inner classes. ++

  • Class to create an instance

Just like calling a normal function (there is no such thing as the new keyword in Java)

val invoice = Invoice()

val customer = Customer("Joe Smith")
Copy the code

Kotlin is the superclass of all classes ==Any== (similar to the Java ==Object== class). Kotlin’s default classes are not inherited and need to be identified with the keyword ==open==

/ / cannot be inherited class Base () {/ / * * *} the open class Base () {/ * * /} class BaseImplement: Base () {/ / * * *}Copy the code

If the derived class does not have a primary constructor, then each subconstructor must initialize its base type using the super keyword or delegate to another constructor to do so. Note that in this case, different subconstructors can call different constructors of the base type:

class MyView : View { constructor(ctx: Context) : super(ctx) constructor(ctx: Context, attrs: AttributeSet) : Super (CTX, attrs) // default argument to simplify operations // constructor(CTX :Context, attrs: AttributeSet? = null) :super( ctx, attrs) }Copy the code

Overriding methods must be open== open== qualified, overriding functions need to be preceded by the ==override== keyword

Open class Shape {open fun draw() {*... */} fun fill() {/*... */}} class Circle() : Shape() {override fun draw() {*... * /}}Copy the code
  • Data classes

We often create classes that just hold data. In Kotlin, this is called a data class and is marked ==data== (Java convention names these classes xxBean,xxEntity)

data class User(val name: String, val age: Int)

Copy the code

The compiler automatically generates the following methods based on the arguments in the main constructor

  1. equal() / hashCode()

  2. ToString () // format User(name= xx,age=xx)

  3. copy()

  4. componentN // componet1 .. ComponentN depends on how many arguments you have

Data classes have the following requirements

  1. The primary constructor must have at least one argument 3

  2. All arguments in the main constructor need to be marked ==var== ==val==

  • Seal type

Official definition: A sealed class is used to represent a restricted class inheritance structure: when a value can have a finite number of types and no other types. In a sense, they are an extension of enumerated classes: the collection of values of enumerated types is also limited, but only one instance of each enumerated constant exists, whereas a subclass of a sealed class can have multiple instances of containable state.

To declare a sealed class, add the sealed modifier before the class name. Although a sealed class can have subclasses, all subclasses must be declared in the same file as the sealed class itself.

sealed class Expr data class Const(val number: Double) : Expr() data class Sum(val e1: Expr, val e2: Expr) : When expression fun eval(Expr: Expr): Double = when(expr) {is Const -> expr. Number is Sum -> eval(expr.e1) + eval(expr.e2) NotANumber -> Double Else clause, because we've covered all cases}Copy the code
  • Enumeration class

The most basic use of enumeration classes is to implement a type-safe enumeration. Enumeration constants are separated by commas and each enumeration constant is an object. Each enumeration is an instance of an enumeration class that can be initialized

enum class Color(val rgb: Int) {
    RED(0xFF0000),
    GREEN(0x00FF00),
    BLUE(0x0000FF)
}

Copy the code
  • Object declarations and object expressions

Kotlin uses object expressions and object declarations to create an object that makes a slight change to a class without declaring a new subclass. In short, I create an object of a modified class, but do not declare a new type

SetOnClickListener (object :View.OnClickListener{override fun onClick(v: View?)) {}})Copy the code

Another way to use it

Open class A(x: Int) {public open val y: Int = x} interface B {... } val ab: A = object: A(1), B {override val y = 15Copy the code

Object expressions are used to get an object directly beyond the definition of a class

Its scope:

var m:Int = 0 mTv.setOnClickListener( object :View.OnClickListener{ override fun onClick(v: View?) {m++ // can access m}})Copy the code

Note: Anonymous objects can be used as types declared only in local and private scopes. If you use an anonymous object as the return type of a public function or as the type of a public property, the actual type of the function or property will be the supertype declared by the anonymous object, or Any if you don’t declare Any. Members added to anonymous objects will not be accessible

Class C {// Private function, so its return type is anonymous object type private fun foo() = object {val x: String = "x"} // Public function, so its return type is Any fun publicFoo() = object {val x: String = "x"} fun bar() {val x1 = foo().x // no problem val x2 = publicFoo().Copy the code

Object declaration:

Kotlin uses the object keyword to declare an object. In Kotlin we can easily obtain a singleton through object declarations. (mostly used to create utility classes)

Object L {val TAG ="-->" fun e(MSG :String){log.e (TAG, MSG)} fun I (MSG :String){log.i (TAG, MSG)} L. E. (" Print something ")Copy the code

Companion objects: Object declarations within a class can be marked with the Companion keyword, so that it is associated with an external class through which we can access the internal elements of the object directly.

class MyClass { companion object Factory { fun create(): MyClass = MyClass()}} val instance = myclass.create () // Access the inner element of the objectCopy the code

We can omit the object name of this object and use Companion instead of the object name to declare:

class MyClass {
    companion object {
    }
}

val x = MyClass.Companion

Copy the code

Note: ++ Only one associated object is allowed in a class.

  • Type the alias

Type aliases provide alternative names for existing types. (Giving a code name does not actually create a type.) Use the keyword == typeAlias ==, which must be defined at the top level

1. Alias the function type

typealias  IntPlus =  (Int,Int) -> Int

typealias Predicate<T> = (T) -> Boolean

Copy the code

extension

Kotlin can extend the properties and methods 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.

  • Extension function

An extension function can add a new method to an existing class without modifying the original class.

Fun receiverType. FunctionName (params) {/ / * * *} recieverType: function of the receiver, also is the object function extension functionName: function name params: parameter can be nullCopy the code

example

Print(){Print(" username $name")} fun main(arg:Array<String>){var User = var User User("Lee") user.print ()Copy the code

If the extension function has the same signature as the member function, the member function takes precedence over the extension function.

Class C {fun foo() {println(" member function ")}} fun c.foo () {println(" extension function ")} fun main(arg:Array<String>){var C = C() C. foo() // call the member function}Copy the code
  • Extended attributes

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.

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

Copy the code
  • Associated object extension
Class MyClass {companion object {} // will be called "companion"} fun myclass.panion.foo () {println(" companion object extension function ")} val MyClass.Companion.no: Int get() = 10 fun main(args: Array<String>) {println("no:${myclass.no}") myclass.foo ()} Functions/attributesCopy the code

entrust

Delegation pattern is a basic skill in software design pattern. In the delegate pattern, two objects participate in processing the same request, and the receiving object delegates the request to the other object. Kotlin directly supports the delegation model, which is more elegant and concise. Kotlin implements delegation through the keyword BY.

In the following example, the Derived class Derived inherits all the methods of the interface Base and delegates an object from the passed Base class to execute those methods.

  1. Commissioned by class
Interface Base {fun print()} class BaseImpl(val x: Int) : Base {override fun print() {print(x)}} class Derived(b: Base) : Base by fun main(args: Array<String>) {val b = BaseImpl(10) Derived(b).print()Copy the code
  1. Attribute to entrust

An attribute value of a class is not directly defined in the class, but entrusted to a proxy class, so as to achieve unified management of the attributes of the class.

Import kotlin.reflect.KProperty class Example {var p: String by Delegate()} class Delegate {operator fun getValue(thisRef: Any? , property: KProperty<*>): String {return "$thisRef, where ${property.name} attribute "} operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {println("$thisRef ${property.name} attribute = $value")}} fun main(args: Array<String>) {val e = Example() println(e.p) // Call getValue() function e.p = "Lee" // call setValue() function println(e.p)}Copy the code

Kotlin generics

To complement…