Kotlin learning Notes (6) — Kotlin classes and objects like and inheritance
Kotlin study Notes series tutorial
Kotlin Study Notes (1) – Overview, Learning Curve, Development Tools, Resources Kotlin Study Notes (2) – Basic Syntax Kotlin Study Notes (3) – Idioms Kotlin Study Notes (4) – Basic types of Kotlin Foundation Study Notes (5) – Kotlin basics control flow, returns and jumps, packages and imports
class
Kotlin uses the keyword class to declare classes
class Invoice {
}
Copy the code
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. Class headers and class bodies are optional; If a class does not have a class body, you can omit the curly braces.
class Empty
Copy the code
The constructor
A class in Kotlin can have a primary constructor and one or more secondary constructors. The primary constructor is part of the class header: it follows the class name (and optional type arguments).
class Person constructor(firstName: String) {
}
Copy the code
If the main constructor does not have any annotations or visibility modifiers, omit the constructor keyword.
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 at the class weight, interwoven with property initializers:
class Kotlin1(fileName: String){
val time = fileName
init {
var size = time.length
}
}
Copy the code
Note: The parameters of the main construct can be used in the initializer block. They can also be used in the property initializer declared inside the class body:
val time = fileName
Copy the code
In fact, Kotlin has a concise syntax for declaring attributes and initializing them from the main constructor:
class Kotlin1(fileName: String,val size: Int,var age: Int){
//....
}
Copy the code
As with normal properties, properties declared in the main constructor can be mutable (var) or read-only (val). The constructor keyword is required if the constructor has annotations or visibility modifiers that precede it:
Class Customer public @inject constructor(name: String) {... }Copy the code
subconstructor
class Kotlin1{
constructor(fileName: String, size: Int, age: Int) {
val time = fileName
}
}
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. To delegate to another constructor of the same class, use this:
class Kotlin1(fileName: String){
constructor(fileName: String, size: Int, age: Int) : this(fileName){
}
}
Copy the code
Note that the code in the initialization block actually becomes part of the main constructor. The delegate to the primary constructor is the first statement of the secondary constructor, so all code in the initialization block is executed before the secondary constructor body. Even if the class does not have a primary constructor, this delegate occurs implicitly and the initialization block is still executed:
class Kotlin1{
init {
print("first")
}
constructor(fileName: String, size: Int, age: Int){
print("second")}}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. The constructor’s visibility is public. If you do not want your class to have a public constructor, you need to declare an empty primary constructor with non-default visibility:
class Kotlin2 private constructor(){
}
Copy the code
Note: On the JVM, if all arguments to the main constructor have default values, the compiler generates an extra no-parameter constructor that takes the default values, making it easier for Kotlin to use libraries like Jackson or JPA that create instances of classes using no-parameter constructors. class Kotlin2 (val fileName: String =""){
}
Copy the code
To create an instance of a class, we call the constructor like a normal function:
val kotlin2 = Kotlin2("music")
Copy the code
Note that Kotlin does not have the new keyword to create nested classes, inner classes, and class instances of anonymous inner classes are described in nested classes.
Members of the class
Classes can contain:
- Constructor and initialization block
- function
- attribute
- Nested classes and inner classes
- Object statement
inheritance
In Kotlin all classes have a common superclass, Any, which is the default superclass for classes without a supertype declaration:
Class Example // implicitly inherited from AnyCopy the code
Note: Any is not java.lang.Object; In particular, in addition to equals(),hashThere are no members outside Code() and toString(). See the Java Interoperability section for more details.Copy the code
To declare an explicit supertype, we place the type after the colon in the class header:
open class Kotlin1{
init {
print("first")
}
constructor(fileName: String, size: Int, age: Int){
print("second")
}
}
class Kotlin2 : Kotlin1("music", 20, 20) {}Copy the code
The open annotation on a class, as opposed to final in Java, allows other classes to inherit from that class. By default, all classes in Kotlin are final, which corresponds to article 17 in the Effective Java book: ** is either designed for inheritance and documented, or inheritance is prohibited.Copy the code
If a derived class has a primary constructor, its base type can (and must) be initialized in place with the primary constructor arguments of the base class.
If there is no primary constructor, then each secondary constructor must either initialize its base type with 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)
}
Copy the code
Override method
As we mentioned earlier, Kotlin strives for clarity. Unlike Java, Kotlin needs to show members that the annotation can overwrite (which we call open) and members that are overwritten:
open class Kotlin1{
init {
print("first")
}
constructor(fileName: String, size: Int, age: Int){
print("second")
}
open fun addSize(){}
fun addAge(){}
}
class Kotlin2 : Kotlin1("music", 20, 20) {override funaddSize() {
super.addSize()
}
}
Copy the code
Override must be added to the kotlin2.addsize () function; if it is not, the compiler will report an error. If a function is not annotated with open and kotlin1.addage (), a subclass is not allowed to define a function with the same signature, with or without Override. In a final class, open members are forbidden.
The member marked override is itself open, that is, it can be overridden in a subclass. If you want to disallow rewrites, use the final keyword:
class Kotlin2 : Kotlin1("music",20,20) {final override funaddSize() {
super.addSize()
}
}
Copy the code
Covering properties
Property override is similar to method override: Properties declared in a superclass and then redeclared in a derived class must begin with Override, and they must have compatible types. Each declared property can be overridden by a property with initialization or a property with getter methods.
open class Kotlin1{
open val aa: Int get() {
return 5
}
}
class Kotlin2 : Kotlin1 {
override val aa: Int
get() = super.aa + 5
}
Copy the code
You can also override a val attribute with a var attribute, but not vice versa. This is allowed because a val property essentially declares a getter method, while overwriting it as var simply declares an additional setter method in a subclass.
Note that you can use the override keyword as part of the property declaration in the main constructor.
interface Foo {
val count: Int
}
class Bar1(override val count: Int) : Foo
class Bar2 : Foo {
override var count: Int = 0
}
Copy the code
Initialization order of derived classes
In the construction of a new instance of a derived class, the first step completes the initialization of its base class (previously only the evaluation of the base class constructor arguments), and therefore occurs before the initialization logic of the derived class runs.
open class Base(val name: String) {
init { println("Initializing Base") }
open val size: Int =
name.length.also { println("Initializing size in Base: $it") }
}
class Derived(
name: String,
val lastName: String
) : Base(name.capitalize().also { println("Argument for Base: $it") }) {
init { println("Initializing Derived") }
override val size: Int =
(super.size + lastName.length).also { println("Initializing size in Derived: $it")}Copy the code
Output:
Constructing Derived("hello"."world")
Argument for Base: Hello
Initializing Base
Initializing size in Base: 5
Initializing Derived
Initializing size in Derived: 10
Copy the code
This means that the base class constructor executes, or override properties are declared in a derived class has not been initialized, if in the base class initialization logic (directly or through another cover the realization of the members of the open indirectly) use any such property, then could lead to incorrect behavior or run time failure, when designing a base class, This use of open members in constructors, property initializers, and init blocks should be avoided
Invoke the superclass implementation
Code in a derived class can use the super keyword to call the implementation of functions and attribute accessors for its superclass:
open class Kotlin1{
init {
print("first")
}
constructor(fileName: String, size: Int, age: Int){
print("second")
}
open fun addSize() {print("Kotlin1")
}
fun addAge(){}
}
class Kotlin2 : Kotlin1("music", 20, 20) {override funaddSize() {
super.addSize()
print("Kotlin2")}}Copy the code
Accessing the superclass of an external class in an inner class can be done with the super keyword qualified by the name of the external class: super@Outer:
class Bar : Foo() {
override fun f() { /* …… */ }
override val x: Int get() = 0
inner class Baz {
fun g() {[email protected]() // call Foo's f() println([email protected]) // Use Foo's getter for x}}}Copy the code
Covers the rules
In Kotlin, implementation inheritance is governed by the following rule: if a class inherits multiple implementations of the same member from its immediate superclass, it must override that member and provide its own implementation (perhaps with one of the inherits). To indicate which supertype to inherit from, we use super qualified by the supertype name in Angle brackets, such as super
open class Kotlin1{
open fun addSize(){}
}
interface A {
fun addSize(){
println("aa")
}
}
class Kotlin2 : Kotlin1("music", 20, 20), A {override funaddSize() {
super<Kotlin1>.addSize()
super<A>.addSize()
}
}
Copy the code
It’s ok to inherit both Kotlin1 and A, but addSize() inherits both implementations from Kotlin2, so we have to override addSize() in Kotlin2 and provide our own implementation to disambiguate.
An abstract class
Classes and some of their members can be declared abstract. Abstract members are not implemented in this class. Note that we do not need to annotate an abstract class fire function with open — this is self-explanatory
We can override a non-abstract open member with an abstract member
open class Base {
open fun f() {}
}
abstract class Derived : Base() {
override abstract fun f()
}
Copy the code
Associated object
Unlike Java or C#, there are no static methods for classes in Kotlin, and in most cases it recommends simply using package-level functions.
If you need to write a function (for example, a factory method) that doesn’t need to be called by an instance of the class, but needs to access the inside of the class, you can write it as a member of the object declaration within the class.
More specifically, if you declare a companion object inside your class, you can call its members using the same syntax as calling static methods in Java/C#, using only the class name as the qualifier.
That was the first article on classes and objects — classes and inheritance
Personal blog: http://outofmemory.top/ CSDN address: http://blog.csdn.net/dazhaoDai making address: https://github.com/dazhaoDai