• Print type name
println(string.javaClass.name)
Copy the code
  • If Kotlin does not declare a return value type, the default return value type is Unit
  • Declare the attributes of the class
inner class Book(var name: String) {
        fun printName(a) {
            println(this.name)
        }
    }
Copy the code
  • Write defensive code using val first
  • Function types
(int) -> Unit() - >Unit
(Int, String) -> Unit
(errorCode: Int, errMsg: String) -> Unit
(errorCode: Int, errMsg: String?) -> Unit
((errorCode: Int, errMsg: String?) -> Unit)?

/** * function type argument */
    fun filter(name:String, filter: (country: Country) - >Unit){}Copy the code
  • The return value is a function
(Int) - > ((Int) - >Unit)
Copy the code
  • The double colon calls the class method class::fun
  • Anonymous functions
  • Invoke () Every Function has an Invoke Function, so to execute the Function body, you need to call the function.invoke ()
private fun foo(int: Int) = { _: Int ->
        println(int.toString() + "fage")}private fun list(a) {
        listOf(1.2.3).forEach { foo(it).invoke(it) }
    }
Copy the code
  • Lambda
    • val sum: (Int, Int) -> Int = {x,y -> x+y}
    • If the Lamba expression returns a value other than Unit, the default last line is its return value
  • Extension function
package com.example.kotlincore

import android.view.View

fun View.invisiable(a) {
    visibility = View.INVISIBLE
}

fun View.gone(a) {
    visibility = View.GONE
}
Copy the code
  • If else ensures code security and eliminates side effects
fun ifExpression(flag: Boolean) {
        val a = if (flag) "fage" else ""
    }
Copy the code
  • Enumeration works with when expressions
package com.example.kotlincore

/** ** what day of the week */
enum class Day(value: Int) {
    MON(1),
    TUE(2),
    WEN(3),
    THU(4),
    FRI(5),
    SAT(6),
    SUN(7)}/** ** schedule */
    fun schedule(sunny: Boolean, day: Day) {
        when(day) {
            Day.SAT -> basketball()
            Day.SUN -> finish()
            Day.FRI -> appointment()
            else -> when {
                sunny -> library()
                else -> study()
            }
        }
    }

    fun basketball(a) {}
    fun fishing(a) {}
    fun appointment(a) {}
    fun library(a) {}
    fun study(a) {}
Copy the code

The generic

The generic class implementation finds whether an element is in an array, returns itself if it is, and returns NULL if it is not

package com.example.kotlincore

/** * find if the array contains an object */
class SmartClass<T> : ArrayList<T>() {
    fun find(t: T) : T? {
        val index = super.indexOf(t)
        return if (index >= 0) super.get(index) else null}}Copy the code

Use extension functions to implement the above requirements

fun <T> ArrayList<T>.find(t: T): T? {
    val index = this.indexOf(t)
    return if (index >= 0) this[index] else null
}
Copy the code

Java generics compatibility

  • Since generics were only introduced in version 1.5 of the real Java, Java allows generic classes without specific type parameters

Type constraint upper bound

/** ** generic class */
class Plate<T>(val t: T)    / / a generic class
open class Fruit(val weight: Double)    / / open classes
class Apple(weight: Double): Fruit(weight)  / / inheritance
class Banana(weight: Double): Fruit(weight) / / inheritance
class FruitPlate<T: Fruit>(val t: T)    // The generic upper bound
Copy the code

Generic erasure

  • Generics in Kotlin and Java are implemented through type erasure. Why
  • Java backward compatibility: when an older version of Java file is compiled to run on a newer version of JVM

Use inline functions to get generics

/** * use an inline function to get the generic type */
inline fun <reified T : Any> Gson.fromJson(json: String) : T {
    return Gson().fromJson(json, T::class.java)
} 
Copy the code

covariance

  • Only reading the out keyword equals that the type passed in can be a subclass of the convention type
/** * covariate */ interface ListCustom<out E> : Collection<E> {}Copy the code

inverter

  • In contrast to covariant, the equivalent type passed in is a parent class that can only be written, not read
interface ListCustom<in E> : Collection<E> {}
Copy the code

Static extension functions for associated objects

object Test {

    @JvmStatic
    fun main(args: Array<String>) {
        Log.d("tag"."fage")}}Copy the code

The library extension function run let also apply takeIf

run

  • Single scope
  • Redefine variables
  • Returns the last object in the range

let apply

  • Similar, except for the return value
  • Apply returns the original object, and let returns the value of the closure, the last line of the closure

also

  • As with Apply, the original object is returned
  • The return value is the receiver of the function

takeIf

  • Not only want to call short, but also want to add conditions, in this case, let appears a little insufficient, need to use takeIf

val result = student.takeIf{it.age > 18}.let{… }

Extensions in Android

  • Add an extension to ImageView
fun ImageView.loadImage(url: String) {
    GlideApp.with(this.context)
            .load(url)
            .placeholder(R.mipmap.xxx)
            .error(R.mipmap.xxx)
            .into(this)}Copy the code

metaprogramming

Data class is converted to Map using reflection

object Mapper {
    
    fun <A : Any> toMap(a : A): Map<String, Any? > {return a::class.members.map { m -> 
            val p = m as KProperty
            p.name to p.call(a)
        }.toMap()
    }
}
Copy the code

Design patterns

Abstract Factory pattern: Provides an interface for creating a set of related or interdependent objects without specifying their concrete classes

package com.example.kotlincore

import java.lang.IllegalArgumentException

interface Computer
class Dell: Computer
class Asus: Computer
class Acer: Computer
class DellFactory: AbstractFactory() {
    override fun produce(a): Computer {
        return Dell()
    }
}

class AsusFactory: AbstractFactory() {
    override fun produce(a): Computer {
        return Asus()
    }
}

class AcerFactory: AbstractFactory() {
    override fun produce(a): Computer {
        return Acer()
    }
}

abstract class AbstractFactory {
    abstract fun produce(a): Computer
    
    companion object {
        inline operator fun <reified T : Computer> invoke(a) : AbstractFactory {
            return when (T::class) {
                Dell::class -> {
                    DellFactory()
                }
                Asus::class -> {
                    AsusFactory()
                }
                Acer::class -> {
                    AcerFactory()
                }
                else- > {throw IllegalArgumentException()
                }
            }
        }
    }
}

fun main(args: Array<String>) {
    val dellFactory = AbstractFactory<Dell>()
    val dell = dellFactory.produce()
}
Copy the code

The Builder pattern: Separates the construction of a complex object from its representation so that the same construction process can create different representations

  • Solve a lot of problems with constructors
  • According to the need to construct
  • Solve the problem when a large number of parameters
package com.example.kotlincore

class Robot private constructor(
        val code: String,
        valbattery: String? .val height: Int? .val weight: Int?
) {
    class Builder(private val code: String) {
        private var battery: String? = null
        private var height: Int? = null
        private var weight: Int? = null
        
        fun setBattery(battery: String?).: Builder {
            this.battery = battery
            return this
        }
        
        fun setHeight(height: Int?).: Builder {
            this.height = height
            return this
        }
        
        fun setWeight(weight: Int?).: Builder {
            this.weight = weight
            return this
        }
        
        fun build(a): Robot {
            return Robot(code, battery, height, weight)
        }
    }
}

fun main(args: Array<String>) {
    val robot = Robot.Builder("007")
            .setBattery("R6")
            .setHeight(300)
            .setWeight(200)
            .build()
}
Copy the code
  • This can be simplified in Kotlin by setting the default values
class Robot1 (
        val code: String,
        val battery: String? = null.val height: Int? = null.val weight: Int? = null
)

fun main(args: Array<String>) {
    val robot1 = Robot1("007")
    val robot2 = Robot1("004", height = 300)
    val robot3 = Robot1("008", height = 300, weight = 200)}Copy the code
  • Use the require keyword to place business constraints on the necessary attributes to make our business more secure
package com.example.kotlincore

class Robot1 (
        val code: String,
        val battery: String? = null.val height: Int? = null.val weight: Int? = null
) {
    init {
        require(weight == null || battery == null) {
            "Battery should be determined when setting weight."}}}fun main(args: Array<String>) {
    val robot1 = Robot1("007")
    val robot2 = Robot1("004", height = 300)
    val robot3 = Robot1("008", height = 300, weight = 200)}Copy the code

Summary: In Kotlin, we should avoid using the Builder pattern as much as possible because Kotlin supports named optional parameters

Behavioral pattern

The observer pattern in Kotlin

import java.util.*

/** ** observed */
class StockUpdate: Observable() {

    val observers = mutableSetOf<Observer>()

    fun setStockChanged(price: Int) {
        this.observers.forEach {
            it.update(this, price)
        }
    }
}

/** ** observer */
class StockDisplay: Observer {
    override fun update(p0: Observable? , p1:Any?). {
        if (p0 is StockUpdate) {
            println("The latest stock price is $p1.")}}}/** ** uses */
    fun observer(a) {
        val su = StockUpdate()
        val sd = StockDisplay()
        su.observers.add(sd)
        su.setStockChanged(100)}Copy the code
  • In this way, the observer pattern is simply implemented

Observable delegate properties in Kotlin

  • The main difference is to make the requirements more specific. We can implement them through interfaces to handle a lot of logic that needs to be listened on
  • Start by writing an interface implementation class
import kotlin.properties.Delegates

interface StockUpdateListener {
    fun onRise(price: Int)
    fun onFall(price: Int)
}
Copy the code
  • Then listen in A Activity
class MainActivity : AppCompatActivity(), StockUpdateListener {
Copy the code
  • The call is then implemented in B Activity
package com.example.kotlincore

import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity

class SecondActivity: AppCompatActivity() {

    companion object {
        fun startActivity(context: Context) {
            val intent = Intent(context, SecondActivity::class.java)
            context.startActivity(intent)
        }
    }

    override fun onCreate(savedInstanceState: Bundle?). {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        delegateObservable()
    }

    /** * observable delegate mode */
    private fun delegateObservable(a) {
        val su = StockUpdate1()
        val sd = MainActivity()
        su.listeners.add(sd)
        su.price = 100
        su.price = 98}}Copy the code

The strategy pattern

Policy patterns are implemented using interfaces to facilitate logical decoupling

package com.example.kotlincore

interface SwimStrategy {
    fun swim(a)
}

class BreastStroke: SwimStrategy {
    override fun swim(a) {
        println("I am breaststroking...")}}class Backstroke: SwimStrategy {
    override fun swim(a) {
        println("I am backstroke")}}class Swimmer(val strategy: SwimStrategy) {
    fun swim(a) {
        strategy.swim()
    }
}

fun main(a) {
    val b1 = Swimmer(Backstroke())
    b1.swim()
    val b2 = Swimmer(BreastStroke())
    b2.swim()
}
Copy the code

Using higher-order functions makes the policy pattern much simpler by passing in functions instead of interfaces

package com.example.kotlincore

fun breaststroke(a) {
    println("I am breaststroking...")}fun backstroke(a) {
    println("I am backstroking...")}fun freestyle(a) {
    println("I am freestroking...")}class Swimmer1(val swimming: () -> Unit) {
    fun swim(a) {
        swimming()
    }
}

fun main(a) {
    val b1 = Swimmer1(::freestyle)
    b1.swim()
    val b2 = Swimmer1(::backstroke)
    b2.swim()
    val b3 = Swimmer1(::breaststroke)
    b3.swim()
}
Copy the code

The template method pattern uses higher-order functions instead of inheritance

  • Most of our business implementations use inheritance patterns or abstract class inheritance patterns to implement template code
  • Example: To run an errand at the civic center, three steps
  • 1: queue with a number
  • 2: Handle specific business
  • 3: evaluation
  • So let’s write an abstract class, 13, 2 implemented by a concrete class
** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** *
abstract class CivicCenterTask {
    fun execute(a) {
        this.lineUp()
        this.askForHelp()
        this.evaluate()
    }
    
    private fun lineUp(a) {
        println("Line up")}private fun evaluate(a) {
        println("Evaluation")}abstract fun askForHelp(a)
}
Copy the code
  • implementation
class PullSocialSecurity: CivicCenterTask() {
    override fun askForHelp(a) {
        println("Pull social Security list.")}}class ApplyForCitizenCard: CivicCenterTask() {
    override fun askForHelp(a) {
        println("Apply for a Citizen card")}}Copy the code
  • use
private fun abstract(a) {
        val pass = PullSocialSecurity()
        pass.execute()
    }
Copy the code

Rely on higher-order functions instead of the above abstract inheritance

class CivicCenterTask2 {
    fun execute(askForHelp: () -> Unit) {
        this.lineUp()
        askForHelp()
        this.evaluate()
    }
    
    private fun lineUp(a) {
        println("Line up")}private fun evaluate(a) {
        println("Evaluation")}}fun pullSocialSecurity(a) {
    println("Pull social Security list.")}fun applyForCitizenCard(a) {
    println("Apply for a Citizen card")}Copy the code
  • use
private fun highFun(a) {
        val pass = CivicCenterTask2()
        pass.execute(::pullSocialSecurity)
    }
Copy the code
  • As you can see, the effect of using higher-order functions is the same as that of using abstract function inheritance, but with much less code. One function will solve the problem