Learning from 0 to 1 by using the Kotlin example, learning from 0 to 1 by using the Kotlin example, Example from 0 to 1 – Kotlin from 0 to 1 – Kotlin from 0 to 1 – Kotlin from 0 to 1 – Kotlin from 0 to 1 – Kotlin from 0 to 1 Example from 0 to 1: the agent from 0 to 1: the agent from 0 to 1 Zero-to-one learning from Examples — Kotlin & JS Translation source

hello world

package org.kotlinlang.play         / / 1

fun main(a) {                        / / 2
    println("Hello, World!")        / / 3
}
Copy the code
  • 1 Kotlin is generally defined in a package. But if you don’t define it then put the content in the default package.
  • 2 mainMethods are the entry points to programs. In the Kotlin 1.3mainMethods may not define any parameters or return values.
  • 3 printlnMethod will input a line of content to standard output. This method is already referenced by default; no explicit reference is required. Semicolons are no longer necessary.

Before version 1.3, the main method had to have arguments

fun main(args: Array<String>) {
    println("Hello, World!")
}
Copy the code

methods

Common methods
fun printMessage(message: String): Unit {                               / / 1
    println(message)
}

fun printMessageWithPrefix(message: String, prefix: String = "Info") {  / / 2
    println("[$prefix] $message")}fun sum(x: Int, y: Int): Int {                                          / / 3
    return x + y
}

fun multiply(x: Int, y: Int) = x * y                                    / / 4

fun main(a) {
    printMessage("Hello")                                               / / 5
    printMessageWithPrefix("Hello"."Log")                              / / 6
    printMessageWithPrefix("Hello")                                     / / 7
    printMessageWithPrefix(prefix = "Log", message = "Hello")           / / 8
    println(sum(1.2))                                                  / / 9
}
Copy the code
  • A simple method that takes a string argument and returns unit is to return void with no value
  • 2 A method with two arguments, where info is a method with a default value and no return value is the default Unit

What does Kotlin’s Java code look like with tools show Kotlin bytecode decompile


fun printMessageWithPrefix(message: String, prefix: String = "Info") {  // 2
    println("[$prefix] $message")
}

fun main() {
    printMessageWithPrefix("1")
    printMessageWithPrefix("1", "2")
}
Copy the code

As you can see from this, kotlin’s handling here is to create a method with a different name, directly changing the location of the call, rather than overloading it as expected

public static final void printMessageWithPrefix(@NotNull String message, @NotNull String prefix) { Intrinsics.checkParameterIsNotNull(message, "message"); Intrinsics.checkParameterIsNotNull(prefix, "prefix"); String var2 = '[' + prefix + "] " + message; boolean var3 = false; System.out.println(var2); } // $FF: synthetic method public static void printMessageWithPrefix$default(String var0, String var1, int var2, Object var3) { if ((var2 & 2) ! = 0) { var1 = "Info"; } printMessageWithPrefix(var0, var1); } public static final void main() { printMessageWithPrefix$default("1", (String)null, 2, (Object)null); printMessageWithPrefix("1", "2"); } // $FF: synthetic method public static void main(String[] var0) { main(); }Copy the code
  • A method that returns the value of int
  • A method that has only one expression and concludes that the return value is int
  • 5 calls the first method and passes in onehelloThe parameters of the
  • 6 calls the second method and passes in two arguments
  • 7 calls the second method and passes in a parameter, info, with a default value info
  • 8 calls the second method to pass in named parameters, so that the parameters are no longer passed in parameter order
  • 9 Print the return value of the method
Infix functions Infix functions

Member methods and extension methods can be converted to infix methods if they have only one parameter

fun main(a) {

  infix fun Int.times(str: String) = str.repeat(this)        / / 1
  println(2 times "Bye ")                                    / / 2

  val pair = "Ferrari" to "Katrina"                          / / 3
  println(pair)

  infix fun String.onto(other: String) = Pair(this, other)   / / 4
  val myPair = "McLaren" onto "Lucas"
  println(myPair)

  val sophia = Person("Sophia")
  val claudia = Person("Claudia")
  sophia likes claudia                                       / / 5
}

class Person(val name: String) {
  val likedPeople = mutableListOf<Person>()
  infix fun likes(other: Person) { likedPeople.add(other) }  / / 6
}
Copy the code
  • Define an infix extension method in an Int class
  • 2 Do it this way
  • Create a pair using the infix method in the standard libraryto
  • Create your own similar totoThe method ofonto
  • 5 Infix symbols can also be defined as member methods for use by class objects
  • The class that defines the infix method will be the first argument in the method, with a default this

Local functions Internal methods define methods within methods

Operator methods

Explicit methods can be upgraded to operator methods that allow callers to perform operations using the corresponding symbols

operator fun Int.times(str: String) = str.repeat(this)       // 1
println(2 * "Bye ")                                          // 2

operator fun String.get(range: IntRange) = substring(range)  // 3
val str = "Always forgive your enemies; nothing annoys them so much."
println(str[0..14])                                          //14
Copy the code
  • The 1 operator corresponds to the overloaded method and The Times method corresponds to *, which is equivalent to the overloaded operator
  • 2 timesCorresponding to the*You call2 * "Bye "It’s equivalent to calling2.times("Bye ")
  • 3 get(range: IntRange) ==> [0 .. 14]
  • 4 You can refer to this article
Method with vararg parameter

Vararg is the Java equivalent of String… args

fun printAll(vararg messages: String) { // 1 for (m in messages) println(m) } printAll("Hello", "Hallo", "Salut", "Hola", Vararg messages: String, prefix: String) {// 3 for (m in messages) println(prefix + m)} printAllWithPrefix("Hello", "Hallo", "Salut", "Hola", "Hello", prefix = "Greeting: " // 4 ) fun log(vararg entries: String) { printAll(*entries) // 5 }Copy the code
  • 1 How do I get each parameter in VARarg
  • 2 You can also pass in any number of arguments including zero
  • 3 Because of named parameters you can add a variable length parameter to a variable length parameter of the same type. 2 This is not possible in Java
  • You should use it like this
  • 5 At runtime, vararg is passed as an array to arguments, just like In Java. You can use*Pass variable-length arguments as variable-length arguments rather than as arrays. An error will be reported if you do not add * here.

variable

Kotlin has a strong ability to infer variables. You can either explicitly define the type of the variable, or you can let the compiler infer what the type of the variable is. Using val is recommended because it is an immutable variable, and kotlin does not force you to do so. You can use var instead.

var a: String = "initial"  // 1
println(a)
val b: Int = 1             // 2
val c = 3                  // 3
Copy the code
  • 1 defines a mutable variable and initializes it
  • 2 defines an immutable variable and initializes it. This is equivalent to adding final to Java
  • 3 defines an immutable variable, initializes it, and does not explicitly define the variable name. The type will be inferred by the compiler, in this case the compiler will infer an Int
var e: Int  // 1
println(e)  // 2
Copy the code
  • 1 defines a variable and does not initialize it
  • 2 An error will be reported and the variable must be initialized

You can initialize it anywhere, as long as it precedes the read variable. This is different from Java

val d: Int  // 1

if (someCondition()) {
    d = 1   // 2
} else {
    d = 2   // 2
}

println(d) // 3
Copy the code
  • Define an immutable variable
  • 2 Perform initialization based on certain conditions
  • 3 The read variable is not an error because it is already initialized

Air safety check

Kotlin wants to create a nullPointerExcept-free world, so assigning a Null value to a variable is not allowed. If you do need to assign null to a variable, append it after its type name.

var neverNull: String = "This can't be null"            // 1

neverNull = null                                        // 2

var nullable: String? = "You can keep a null here"      // 3

nullable = null                                         // 4

var inferredNonNull = "The compiler assumes non-null"   // 5

inferredNonNull = null                                  // 6

fun strLength(notNull: String): Int {                   // 7
    return notNull.length
}

strLength(neverNull)                                    // 8
strLength(nullable)                                     // 9
Copy the code
  • 1 defines a non-null String and assigns a value
  • 2 Set this string to null (an error will be reported here)
  • 3 Define a nullable String and assign a value
  • 4 Set this string to null, and no error is reported
  • Define a variable inferred by the compiler, which in this case is inferred as String. The compiler will preferentially infer that the variable is of a non-null type
  • Error 6, because the compiler will infer when
  • 7 defines a method that takes a non-null String argument
  • 8 the value passed in is a non-empty String value, and no error will be reported here
  • 9 The nullable String passed in? Value, an error will be reported here

Sometimes you have to handle null values, either because Java code passes in null or because NULL represents a state, and Kotlin provides a way to handle null values

fun describeString(maybeString: String?) : String { // 1 if (maybeString ! = null && maybeString.length > 0) { // 2 return "String of length ${maybeString.length}" } else { return "Empty or null string" // 3 } }Copy the code
  • 1 defines a method that can enter a nullable String and returns a non-nullable String
  • 2 Check whether maybeString is empty or an empty string, if so, return the length of maybeString
  • Otherwise, the caller is told that the passed argument is empty or an empty string

class

A class definition consists of the class name, the class header (which contains the type declaration, private constructor, and so on), and the class body, and consists of curly braces. Both the class header and the class body can be default. If the class body defaults, braces can also default.

class Customer                                  // 1

class Contact(val id: Int, var email: String)   // 2

fun main() {

    val customer = Customer()                   // 3
    
    val contact = Contact(1, "[email protected]")  // 4

    println(contact.id)                         // 5
    contact.email = "[email protected]"            // 6
}
Copy the code
  • Define a class Customer that does not define any attributes or constructors. Kotlin will automatically assign a no-parameter constructor
  • Define a Contact class with an immutable variable id, a mutable variable email, and a constructor with two parameters
  • 3 Create an immutable variable instance customer whose type is inferred to be Customer. Use the default constructor for Customer. There is no new keyword in Kotlin
  • Create an instance of Contact using a constructor with two parameters
  • 5 Obtain the ID of the contact attribute
  • 6 Update the email attribute of contact

The generic

Generics are a template method found in modern languages. Generic classes and generic methods make code highly reusable. Just like the internal logic in List

has no logical relationship with T

A generic class

The first way to use generics is with generic classes

class MutableStack<E>(vararg items: E) {              // 1

  private val elements = items.toMutableList() 

  fun push(element: E) = elements.add(element)        // 2

  fun peek(): E = elements.last()                     // 3

  fun pop(): E = elements.removeAt(elements.size - 1)

  fun isEmpty() = elements.isEmpty()

  fun size() = elements.size

  override fun toString() = "MutableStack(${elements.joinToString()})"
}
Copy the code
  • Define a generic class. E can be called a generic parameter. When you defineMutableStack<Int>Int is called a generic parameter
  • You can use E instead of generic arguments in methods of generic classes
  • 3 You can also substitute E for the return value
Generic method

You can of course define generic methods if their logic has nothing to do with generic parameters. For example, you could define a method like this

fun <E> mutableStackOf(vararg elements: E) = funmain () {val stack = funmain () println(stack)}Copy the code

Note: compilation will infer that mutableStackOf is a Double MutableStack so you don’t need to fill in mutableStackOf

(…) Such as


inheritance

Kotlin supports a traditional object-oriented inheritance mechanism

open class Dog { // 1 open fun sayHello() { // 2 println("wow wow!" ) } } class Yorkshire : Dog() { // 3 override fun sayHello() { // 4 println("wif wif!" ) } } fun main() { val dog: Dog = Yorkshire() dog.sayHello() }Copy the code
  • 1 Kotlin classes are final by default. If you want to allow classes to be inherited, you need to add the open keyword before the class.
  • 2 Kotlin’s methods are also final by default. If you want to allow methods to be overridden, you need to add the open keyword before fun.
  • A subclass should be defined in : SuperclassName()Before. empty(a)Means super is the default constructor for the parent class.
  • Override should be added to overriding method summation attributes
Inheritance of constructors with arguments
open class Tiger(val origin: String) { fun sayHello() { println("A tiger from $origin says: grrhhh!" ) } } class SiberianTiger : Tiger("Siberia") // 1 fun main() { val tiger: Tiger = SiberianTiger() tiger.sayHello() }Copy the code
  • If you want to define a subclass using the constructor of the parent class, you need to pass in the fields passed to the parent class at the time of definition.
Pass arguments to the parent class
open class Lion(val name: String, val origin: String) { fun sayHello() { println("$name, the lion from $origin says: graoh!" ) } } class Asiatic(name: String) : Lion(name = name, origin = "India") // 1 fun main() { val lion: Lion = Asiatic("Rufo") // 2 lion.sayHello() }Copy the code
  • 1 AsiaticThe name in the class is neither val nor var. This is a constructor parameter that is used only to pass the value to the constructor of the parent class.
  • Create an instance of Asiatic with the constructor parameter Rufo. This call will use the parent classLionThe two-parameter construction method of the