Eliminating static tool classes: top-level functions and attributes
Code in Java is written into the functions of classes, but most of the time the classes created are just containers for static functions. But there is no need to create meaningless classes in Kotlin. It can put functions directly at the top of the code file without subordinating to any classes.
Take a chestnut and create a string package
Create joinToString function under package strings
fun<T> joinToString(collection: Collection<T>, separator: String= "", prefix: String = "", postfix: String = ""): String{ val result = StringBuilder(prefix) for ((index,element) in collection.withIndex()){ if(index > 0) result.append(separator) result.append(element) } result.append(postfix) return result.toString() }
Call this function in kotlin
fun main() { val list = listOf(1,2,3) //Calling four parameters to assemble array elements val res = com.example.kotlinoflearn.function.joinToString(list, ",", "(", ")") println(res) }
Results: (1,2,3)
So how do you call this function in Java?
To call this function, you must import the package file. Because the file name of the function is TopFunction, the compiler compiles the file into a TopFunctionK class when compiling it. And compile joinToString into static classes
import strings.TopFunctionKt;
Set<Integer> set = new HashSet<>(); set.add(1); set.add(2); set.add(3); String res = TopFunctionKt.joinToString(set,",","(",")"); System.out.println(res);
You can see the same way to call joinToString functions as to call static functions.
Results: (1,2,3)
spread function
- Extension function: A member function of a class, but defined outside the class
- The extended class is called the receiver type, and the object used to call the extension function is called the receiver object.
- Note: Extension functions do not allow you to break their encapsulation. Unlike class internal definitions, extension functions do not have access to private or protected members.
For example, the join ToString function above can be changed to an extension function of Collection.
fun<T> Collection<T>.joinToString( separator: String= "", prefix: String = "", postfix: String = ""): String{ val result = StringBuilder(prefix) //This is the class in the extension function, such as this - > Collection for ((index,element) in this.withIndex()){ if(index > 0) result.append(separator) result.append(element) } result.append(postfix) return result.toString() }
Note: Rewriting member functions is common, but extensions are not. For an extension function, it is not part of a class, but is declared outside the class. So when it's called, which one to use is determined by the static type of the variable
Take a chestnut
Write a parent class View and a function click, and a child class Button overrides the click function.
open class View{ open fun click() = println("View clicked") } class Button: View(){ override fun click() = println("Button clicked") }
Define a Button instance and call the click function
val v: View = Button() println(v.click()) // Button clicked
Results: Button clicked
It is found that the output is Button clicked, which is the result of the subclass rewriting the parent click function.
What would be the result of adding extension functions to these two classes?
Add showOff extension function
fun View.showOff() = println(" I am a view!") fun Button.showOff() = println("I am a button!")
Calling Extension Functions
val v: View = Button() println(v.showOff())
Output: I am a view!
It verifies the previous conclusion that the extension function does not support rewriting. When it is called, which one to use is determined by the static type of the variable. The static type here is View type, so the extension function showOff of View is called.
Extended attributes
The implementation of extended attributes is somewhat similar to that of extended functions, but extended attributes must write getter methods because they do not have default implementations.
- If attributes are immutable, just write getter functions, such as String types.
- If attributes are variable, you need to write setter and getter functions, such as StringBuilder types.
val String.lastChar: Char get() = get(length - 1) var StringBuilder.lastChar: Char get() = get(length - 1) set(value: Char){ this.setCharAt(length - 1,value) }
summary
Learning Kotlin is not only a process of learning a new language, but also a process of learning to change habitual ways of thinking.
Compared with Java, Kotin brings you different thinking habits
- Kotlin can define default values for function parameters, which greatly reduces the need for overloaded functions, and named parameters make the call of multi-parameter functions more readable.
- Kotlin can extend API s of any class with extension functions and attributes, including classes defined in external libraries, without modifying their source code or running time overhead.
- Kotlin allows for a more flexible code structure: functions and attributes can be declared in files, not just as members of classes
Last
If you see it here and think it's a good article, give it a compliment! _____________ Welcome to comment and discuss! If you think it's worth improving, please leave me a message. We will make serious inquiries, correct shortcomings, and regularly share technical dry goods free of charge. Thank you!