Kotlin detailed article notes collation update progress: Kotlin Series – High order functions and Common functions in standard Library (3) Kotlin Series – Advanced Deep Generic Covariant Inversion from Java to Kotlin(4) Koltin series – Coroutines from Recognition to Use in Android (5)
1. Function inheritance and implementation, copying, etc
- The parent class need
open
Can be inherited (kotlin
The default isfinal
) - The mode of the parent class, the attribute needs
open
Before it can be overwritten - Interfaces, interface methods, and abstract classes default to
open
- Overrides the parent (interface) member required
override
The keyword - Note that when you inherit a class, you are actually calling the constructor of the parent class
- Classes can only be inherited singly, and interfaces can be implemented multiple times
abstract class Person(open val age: Int){
abstract fun work()
}
class MaNong(age: Int): Person(age){
override val age: Int
get() = 0
override fun work() {
println("I'm a coder. I'm writing code.")
}
}
class Doctor(override val age: Int): Person(age){
override fun work() {
println("I'm a doctor. I'm treating patients.") } } fun main(args: Array<String>) { val person: Person = MaNong(23) person.work() println(person.age) val person2 : Person2 Person = Doctor (20). The work () println (person2. Age)} -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- printed I am a code farmer, I am writing code 0 I'm a doctor, I'm seeing a patientCopy the code
Interface proxy (by
)
The interface method implementation is handed over to the proxy class
class Manager(diver:Driver): Driver by driver
Copy the code
3. Interface method conflict (implementing multiple interfaces)
- Interface methods can have default implementations
- Conflicts with consistent signatures (consistent method names, parameters, etc.) and the same return value
- Implementation classes must override conflicting methods
- Super <[interface name]>. Method name (parameter list)
abstract class A{
open fun x(): Int = 5
}
interface B{
fun x(): Int = 1
}
interface C{
fun x(): Int = 0
}
class D(var y: Int = 0): A(), B, C{
override fun x(): Int {
println("call x(): Int in D")
if(y > 0){
return y
}else if(y < -200){
return super<C>.x()
}else if(y < -100){
return super<B>.x()
}else{
return super<A>.x()
}
}
}
Copy the code
4. Visibility of classes and their membersprivate protect interanl public
Protected: visible in subclasses internal: visible in modules
5. Object
The keyword
- A class that has only one instance
- You cannot customize constructors
- You can implement interfaces and inherit parent classes
- This is essentially the most basic implementation of the singleton pattern
Public final class TestKotlin {public static final TestKotlin INSTANCE; privateTestKotlin() { } static { TestKotlin var0 = new TestKotlin(); INSTANCE = var0; }}Copy the code
6. companion object
Associated objects, static variable members andkotlin
Package level members
kotlin
Allows not writing member variables and methods under a class, calledPackage-level objects/functions- Each class can have one associated object for each pair
companion object
- Associated object
companion object
withjava
thestatic
Static methods/static members have similar effects. kotlin
Static members are considered to be replaced by package-level functions and variablesJvmField
,JvmStatic
,@file:JvmName(custom class name)
package com.demo.dan.voice
val Str = "Package member"
fun packFun(): String {
return "Package level function"
}
class TestKotlin {
companion object {
fun compainFun(): String {
return "Companion object method"
}
var Str = "Companion Object Member"}}Copy the code
Called in Koltin and Java
//-------------- call fun in kotlinmain() {println (Str) / / package level members println (packFun ()) / / package level function TestKotlin. Str TestKotlin.com painFun ()} / / -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - call in Java public class TestJava { public static void main(String[] args) { TestKotlin.Companion.compainFun(); TestKotlin.Companion.getStr(); }Copy the code
You can see that the above Java code for calling Kotlin is not like our Java code for calling static objects (with additional layers of Companion).
The above Java call to Kotlin can add corresponding annotations to the accompanying object: @jVMStatic on the function and @jVMField on the variable
The implementation is similar to calling Java static members/methods
class TestKotlin {
companion object {
@JvmStatic
fun compainFun(): String {
return "Companion object method"
}
@JvmField
var Str = "Companion Object Member"Public class TestJava {public static void main(String[] args) {TestKotlin.compainFun(); String str = TestKotlin.Str; }}Copy the code
For details, you can go to Kotlin to Java and see the difference between annotated and unannotated, but I won’t add code here for space reasons.
How does Java call Kotlin’s package-level objects?
Answer: Use @file:JvmName(your own custom class name)
@file:JvmName("TestKotlin1")
package com.demo.dan.imoc_voice
val Str = "Package member"
fun packFun(): String {
return "Package level function"
}
Copy the code
Java calls:
public class TestJava { public static void main(String[] args) { TestKotlin1.getStr(); TestKotlin1.packFun(); }}Copy the code
7. Method overloading and default parameters
Overloads
Method overloading- Methods with the same name and different parameters
Jvm
Concept of function signature: function name, argument list (no return value!) , when two methods have the same method name and argumentJvm
Think of it as a function.kotlin
You can set default values for function parameters in the.- Use named functions when there is confusion over function calls
// The following two functions are signed by the same function. Fun (a) : Int {} fun () : a String {} / / method overloading fun (s: Stirng) {} a fun a (s: String, I: Int) {} -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- example -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - / / kotlin provides default function, Funa (s:String =); // If funa (s:String =); // If funa (s:String ="ss",i:Int){}
fun main() {
a(str ="str")}Copy the code
java
How to callkotlin
The default argument to the function?? Answer: Use@JvmOverloads
annotations
---------- @file:JvmName("TestKotlin1") package com.demo.dan.imoc_voice @JvmOverloads fun a(int:Int=1,str: ------------ public class TestJava {public static void main(String[] args) {testkotlin1.a ("dfsdf"); }}Copy the code
java
Method overloadbug
, e.g.List
List.remove(int)
List.remove(Object)
Copy the code
When you pass in an int in a List and you pass in a 4 does remove() remove the fourth bit of data or does it remove the 4 object? Here it calls remove(int) by default, but remove(Object) is not called.
8. Expand membership
Add methods, attributes to existing classes
- Extended method format
fun X.y():Z{... }
(Fun is extended to the class. Custom extension method name (): return type {method body}
) - Extended property format
var X.m
(Var extends the class. Custom extended attribute name
Note that extended attributes cannot be initialized, similar to interface attributes (X
Is the extended class) java
Calling an extended member is similar to calling a static method
@file:JvmName("TestKotlin1") package com.demo.dan.voice // Extend String add multiply method Fun String.multiply(int: int): String { val stringBuilder = StringBuilder()for (i in 0 until int) {
stringBuilder.append(this)
}
returnStringbuilder.tostring ()} // Extend String to add operator - operator fun String. Minus (int: int): String {returnThis.substring (0, length-int+1)} // Extend the member variable val string. a: String get() ="Extended member variable"// Extend member variable var string. b: Intset(value){}
get() = 6
Copy the code
Kotlin call
fun main(args: Array<String>) {
println("I'm a coder.".multiply(3))
println("I'm a coder." - 2)
println("".a)
println("". B)} -- -- -- -- -- -- -- -- -- -- -- -- print Log -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - I'm a code I am a farmer I am yard farmers I am member variables 6 yards extensionCopy the code
Java calls
public static void main(String[] args) {
String str = TestKotlin1.minus("I'm a Java call", 2); String strpr = TestKotlin1.getA(""); System.out.println(str); System.out.println(strpr); } -- -- -- -- -- -- -- -- -- -- -- -- print Log -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - I'm a Java extension member variablesCopy the code
9. Property broker
val delega1 by lazy { }
by
parsing
public inline operator fun <T> Lazy<T>.getValue(thisRef: Any? , property: KProperty<*>): T = valueCopy the code
You can see that BY is actually an operator, where the Lazy extension getValue method is used.
lazy
The principle of analytic
@file:kotlin.jvm.JvmName("LazyKt"1 public actual fun <T> lazy(initializer: () -> T): Lazy<T> = SynchronizedLazyImpl(initializer) private class SynchronizedLazyImpl<out T>(initializer: () -> T, lock: Any? = null) : Lazy<T>, Serializable {2 private var initializer: (() -> T)? @volatile private var _value: Any? = UNINITIALIZED_VALUE // final field is required toenablesafe publication of constructed instance private val lock = lock ? : this override val value: Tget() {val _v1 = _valueif(_v1 ! == UNINITIALIZED_VALUE) { @Suppress("UNCHECKED_CAST")
return_v1 as T} //return synchronized(lock) {
val _v2 = _value
if(_v2 ! == UNINITIALIZED_VALUE) { @Suppress("UNCHECKED_CAST") (_v2 as T)
} else{ val typedValue = initializer!! () _value = typedValue initializer = null typedValue } } } override fun isInitialized(): Boolean = _value ! == UNINITIALIZED_VALUE override fun toString(): String =if (isInitialized()) value.toString() else "Lazy value not initialized yet."
private fun writeReplace(): Any = InitializedLazyImpl(value)
}
Copy the code
Dissecting lazy
Key code 1: Pass the code block after lazy(Initializer: () -> T) to SynchronizedLazyImpl(Initializer)
Key code 2: Go to SynchronizedLazyImpl and assign the code block passed to Initializer
Key code 3: _value is initially uninitialized.
Key code 4: Returns directly if _value is not empty (does not execute the method inside the code block after lazy that we passed)
Key code 5: If _value is null, we do a synchronization check. If it is not null, we return it (without executing the lazy method we passed in). Otherwise, we execute our passed block initializer and initialize _value with the return value
Every time we call the lazy proxy object, we’re actually calling the get() of the value inside, and the first call will run our val delega1 by lazy {code block} code block, After instantiating SynchronizedLazyImpl#_value, the second start is to return the object directly. Keep only one object instance in existence.
-
The above is
val
Property,lazy
Can the agentvar
Is the property of?Answer: No. There’s no method that implements setValue.
-
Custom implementation proxy Let’s use an example to implement a proxy ourselves.
class Delegates{
val hello by lazy {
"HelloWorld"} var hello2 by X() {var hello3 by X()} var hello3 by X()} var hello2 by X() {var hello3 by X()setValue getValue class X{ private var value: String? = null operator fun getValue(thisRef: Any? , property: KProperty<*>): String { println("getValue: $thisRef -> ${property.name}")
returnvalue? :""
}
operator fun setValue(thisRef: Any? , property: KProperty<*>, value: String){ println("setValue, $thisRef -> ${property.name} = $value")
this.value = value
}
}
fun main(args: Array<String>) {
val delegates = Delegates()
println(delegates.hello)
println(delegates.hello2)
println(delegates.hello3)
delegates.hello3 = "value of hello3"Println (delegates. Hello3)} ------------- delegates to Log HelloWorld getValue: com.demo.dan.imoc_voice.Delegates@7530d0a -> hello2 getValue: com.demo.dan.imoc_voice.Delegates@7530d0a -> hello3setValue, com.demo.dan.imoc_voice.Delegates@7530d0a -> hello3 = value of hello3
getValue: com.demo.dan.imoc_voice.Delegates@7530d0a -> hello3
value of hello3
Copy the code
Above we implement a proxy class and implement setValue and getValue methods. This allows you to proxy member variables of type VAR. You can see that when we call it we actually call the setValue and getValue methods of the proxy class.
10. Data classesdata
&&special writing &&solutionJavabean
The problem of
- It’s implemented by default
Copy, toString
, as well ascomponentN
Methods such as - A direct replacement
javaBean
There are problems (possible failure to initialize, unequal constructor signatures) becausejavaBean
The class is notfinal
A type can be inherited and has a no-argument constructor.
Define a data data class
data class TestKotlin(val name:String,val age:Int)
Copy the code
Take a look at the implementation of the conversion to Java
public final class TestKotlin {
@NotNull
private final String name;
private final int age;
@NotNull
public final String getName() {
return this.name;
}
public final int getAge() {
return this.age;
}
public TestKotlin(@NotNull String name, int age) {
Intrinsics.checkParameterIsNotNull(name, "name");
super();
this.name = name;
this.age = age;
}
@NotNull
public final String component1() {
return this.name;
}
public final int component2() {
return this.age;
}
@NotNull
public final TestKotlin copy(@NotNull String name, int age) {
Intrinsics.checkParameterIsNotNull(name, "name");
returnnew TestKotlin(name, age); } / /$FF: synthetic method
public static TestKotlin copy$default(TestKotlin var0, String var1, int var2, int var3, Object var4) {
if((var3 & 1) ! = 0) { var1 = var0.name; }if((var3 & 2) ! = 0) { var2 = var0.age; }return var0.copy(var1, var2);
}
@NotNull
public String toString() {
return "TestKotlin(name=" + this.name + ", age=" + this.age + ")";
}
public int hashCode() {
String var10000 = this.name;
return(var10000 ! = null ? var10000.hashCode() : 0) * 31 + this.age; } public boolean equals(@Nullable Object var1) {if(this ! = var1) {if (var1 instanceof TestKotlin) {
TestKotlin var2 = (TestKotlin)var1;
if (Intrinsics.areEqual(this.name, var2.name) && this.age == var2.age) {
return true; }}return false;
} else {
return true; }}}Copy the code
- You can see
TestKotlin.java
是final
Type, and the constructor has no parameterless.- Implemented inside
component1
.component2
It’s actually a member variable.- It’s implemented by default
toString
,hashCode
,equals
Methods.
Let’s call our TestKotlin data class
fun main() {
val t = TestKotlin("Dennis". 24) println(t.component1()) println(t.component2()) val (name,age)=t println(name) println(age)} ----------- The Log that is printed out 24 Dennis 24Copy the code
val (name,age)=t
So this particular notation is going to bedata
Object of type.
We also iterate over arrays like this:
fun main(args:Array<String>) {
for ((index,value)inArgs. WithIndex () {}} -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- see withIndex implementation public fun < T > Array < T > out. WithIndex () : Iterable<IndexedValue<T>> {returnIndexingIterable {iterator()} --------------------- Return IndexedValue public data class IndexedValue<out T>(public val index: Int, public val value: T)Copy the code
Finally, you can see that IndexedValue is the same data type.
- Deal with alternative
javaBean
Problems can be used,allOpen
withnoArg
Plugins, the former helps us remove the pre-classfinal
The latter is generatedNo parameter constructor
Usage:
- In the project,
Project
) under thebuild.gradle
Buildscript {// the component utility ext.kotlin_version ='1.3.50'
repositories {
google()
jcenter()
mavenCentral()
}
dependencies {
......
classpath "org.jetbrains.kotlin:kotlin-noarg:${kotlin_version}"
classpath "org.jetbrains.kotlin:kotlin-allopen:${kotlin_version}"}}Copy the code
2. Build. Gradle in the corresponding module
apply plugin:'kotlin-noarg'
apply plugin:'kotlin-allopen'NoArg {/ / com. Demo. Dan. Annotations. PoKo PoKo / / this class is created by yourself, to yourself a new annotations directory under / / and create a class, then write the path in the annotation ("com.demo.dan.annotations.PoKo"} allOpen{// annotation("com.demo.dan.annotations.PoKo")}Copy the code
- Create the corresponding package name and file
. \annotatios\PoKo.kt
annotation class PoKo
Copy the code
- in
data
Add an annotation above the class name of the class
@PoKo
data class TestKotlin(val name: String, val age: Int)
Copy the code
- After the above annotation operation, and
rebuild
Let’s convert it tojava
code
public class TestKotlin { ................ Omit the other code publicTestKotlin() {}}Copy the code
You can see that this has helped us generate the no-argument constructor and remove the final modifier keyword.
Note: Since annotations take effect at compile time, we still call the no-argument constructor when we write code, but we can get the no-argument constructor by reflection.
Inner classes && Anonymous inner classes
kotlin
Static inner classes are used by default; non-static inner classes are requiredinner
The keyword
Inner class TestKotlin1{Inner class Inner1{} funmain() {
val inner = TestKotlin.Inner()
val inner1 = TestKotlin1().Inner1()
}
Copy the code
A non-static inner class can be used when the inner class needs the state of the outer class, because the non-static inner class holds a reference to the outer class by default. If you don’t need to hold a reference to an external class, use a static inner class.
@Outter
When a non-static inner class has the same member name as an outer class, you can use theThis@External class name. Member variables
class TestKotlin1 {
val a = "TestKotlin1-string"
inner class Inner1 {
val a = "Inner1-string"
fun aInnerfun(): String {
return a
}
fun aTestKotlinfun(): String {
return [email protected]
}
}
}
Copy the code
- Anonymous inner class (
object
The use of)
------------------kotlin val view = view (context) view.onClickListener = object: View.OnClickListener{ override fun onClick(v: View?) {}} ---------------- View View = null; view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
Copy the code
Unlike Java,Ktolin’s Object also supports simultaneous implementation of single inheritance and multiple implementations
interface TestInterface{
fun test()
}
view.onClickListener = object: TestInterface,View.OnClickListener {
override fun test() {
TODO("not implemented") //To change body of created functionsuse File | Settings | File Templates. } override fun onClick(v: View?) {}}Copy the code
12. The enumeration class
- For a class with finite (countable) instances, an enumeration member corresponds to an instance of the class, because the number of members you write is fixed, so the corresponding instances are fixed.
Enum class LogLevel {VERBOSE, DEBUG, INFO, WARN, ERROR} - similar to the following kotlin code class LogLevel2 protected constructor {companion object{ val VERBOSE = LogLevel2() val DEBUG= LogLevel2() val INFO= LogLevel2() val WARN= LogLevel2() val ERROR= LogLevel2() } }Copy the code
- If the
kotlin
theenum
To define a method, remember to use;
Separate members from methods
enum class LogLevel(val id:Int){
VERBOSE(0),DEBUG(1),INFO(2),WARN(3),ERROR(4) ;
fun getTag():String{
return "$id.$name"}}Copy the code
13. Sealed classsealed class
Classes with finite (countable) subclasses: A subclass can only exist in the same file, so no other file can inherit it, so the subclass is finite (countable).
- Kotlin version
- Koltin version >= V1.1, subclasses only need to be in the same file as the sealed class
- Used to protect a class from external inheritance, it is also final.
sealed class PlayerCmd {
class Play(val url: String, val position: Long = 0): PlayerCmd()
class Seek(val position: Long): PlayerCmd()
object Pause: PlayerCmd()
object Resume: PlayerCmd()
object Stop: PlayerCmd()
}
Copy the code