Kotlin class and object, and Kotlin Class Object Inheritance
Class
Use the class keyword to declare a class in Kotlin
class Invoice { }
The class Declaration consists of the class name, Class header (specifying its type parameter, main constructor, etc.), and the class body surrounded by curly brackets. Both the Class header and class body are optional. If a class has no class body, you can omit curly braces.
class Empty
Constructor
A class in Kotlin can haveMain ConstructorAnd one or moreConstructorThe main constructor is a part of the Class header: it follows the class name (and optional type parameters.
class Person constructor(firstName: String) { }
If the main constructor does not have any annotation or visibility modifier, You can omit this constructor keyword.
class Person(firstName: String) { }
The main constructor cannot contain any code. The initialization code can be prefixed with the init keywordInitialization Block(Initializer blocks.
During instance initialization, the initialization blocks are executed in the order they appear in the Class Weight and are intertwined with the attribute initiators:
class Kotlin1(fileName: String){ val time = fileName init { var size = time.length }}
Note: The parameters of the main structure can be used in the initialization block, or they can be used in the attribute initializer declared in the class body:
val time = fileName
In fact, Kotlin has a concise syntax for declaring attributes and initializing attributes from the primary constructor:
class Kotlin1(fileName: String,val size: Int,var age: Int){ //.... }
Like common attributes, attributes declared in the main constructor can be variable (var) or read-only (val ).
If the constructor has annotation or visibility modifier, this constructor keyword is required and these modifiers are before it:
class Customer public @Inject constructor(name: String) { …… }
Constructor
class Kotlin1{ constructor(fileName: String, size: Int, age: Int) { val time = fileName }}
If a class has a primary constructor, each constructor needs to be delegated to the primary constructor, which can be delegated directly or indirectly through another constructor. You can use the this keyword to delegate another constructor to the same class:
class Kotlin1(fileName: String){ constructor(fileName: String, size: Int, age: Int) : this(fileName){ } }
Note that the code in the initialization block is actually part of the main constructor. The delegate to the main constructor serves as the first statement of the sub-constructor. Therefore, all the code in the initialization block will be executed before the sub-constructor. Even if this class does not have a primary constructor, such delegation will still occur implicitly and the initialization block will still be executed:
class Kotlin1{ init { print("first") } constructor(fileName: String, size: Int, age: Int){ print("second") } }
If a non-abstract class does not declare any (primary or secondary) constructor, it will have a generated primary constructor without parameters. 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(){ }
Note: On JVM, if all parameters of the main constructor have default values, the compiler generates an extra non-parameter constructor, which uses the default value, this makes it easier for Kotlin to create a library of class instances through a non-argument constructor like Jackson or JPA. Class Kotlin2 (val fileName: String = ""){}
Create a class instance
To create an instance of a class, we call the constructor like a common function:
val kotlin2 = Kotlin2("music")
Note that Kotlin does not have the new Keyword
Examples of creating Nested classes, internal classes, and anonymous internal classes are described in the nested classes.
Class Member
Classes can include:
-Constructor and initialization Block
-Function
-Attributes
-Nested and internal classes
-Object Declaration
Inheritance
In Kotlin, all classes have a common superclass.Any, which is the default superclass for classes without the supertype declaration:
Class Example // inherit from Any implicitly
Note: Any is not a java. lang. Object. In particular, it has no members except equals (), hashCode (), and toString. For more details, refer to Java interoperability section.
To declare an explicit supertype, we put the type after the colon of the Class header:
open class Kotlin1{ init { print("first") } constructor(fileName: String, size: Int, age: Int){ print("second") } } class Kotlin2 : Kotlin1("music",20,20) { }
The open Annotation on the class is opposite to final in Java, which allows other classes to inherit from this class. By default, all classes in Kotlin are final, corresponding to article 17th in objective Java: ** either designed for inheritance and provides instructions, or prohibit inheritance **.
If a derived class has a primary constructor, its base type can (and must) be initialized locally using the primary constructor parameters of the base class.
If there is no primary constructor, each constructor must use the super keyword to initialize its base type or delegate it to another constructor. Note: In this case, different constructors can call different constructors of the base type:
class MyView : View { constructor(ctx: Context) : super(ctx) constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs) }
Overwrite Method
As we mentioned before, Kotlin strives to be clear. Unlike Java, Kotlin needs to display the members that can be covered (we call it open) and the covered members:
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 fun addSize() { super.addSize() } }
The Kotlin2.addSize () function must be addedOverrideAnnotation. If it is not written, the compiler will report an error. If the function is not labeledOpenAnd Kotlin1.addAge (), then the function with the same signature cannot be defined in the subclassOverride. In a final class, open members are prohibited.
The member marked as override is open, that is, it can be overwritten in the subclass. If you want to disable overwriting again, use the final Keyword:
class Kotlin2 : Kotlin1("music",20,20) { final override fun addSize() { super.addSize() } }
Overwrite attributes
Property override and method override are similar: Attributes declared in the superclass and re-declared in the derived class must start with override and must have compatible types. Each declared attribute can be overwritten by an attribute with initialization or the getter method.
open class Kotlin1{ open val aa: Int get() { return 5 } } class Kotlin2 : Kotlin1 { override val aa: Int get() = super.aa + 5 }
You can also use a var attribute to overwrite a val attribute, but not vice versa. This is allowed, because a val attribute essentially declares a getter method, and overwriting it as var only declares an additional setter method in the subclass.
Note that you can use the override keyword in the main constructor as part of the attribute declaration.
interface Foo { val count: Int } class Bar1(override val count: Int) : Foo class Bar2 : Foo { override var count: Int = 0 }
Class initialization order
In the process of constructing a new instance of a derived class, the first step is to initialize the base class (only evaluate the parameters of the base class constructor ), this occurs before the initialization logic of the derived class is run.
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") }
Output:
Constructing Derived("hello", "world") Argument for Base: Hello Initializing Base Initializing size in Base: 5 Initializing Derived Initializing size in Derived: 10
This means that during the execution of the base class constructor, the attributes declared or overwritten in the derived class are not initialized yet, if any of these attributes are used in the base class initialization logic (either directly or indirectly through the implementation of another covered open member), it may lead to incorrect behavior or runtime failure, when designing a base class, you should avoid using open members in constructors, attribute initiators, and init blocks.
Call the superclass implementation
The code in the derived class can use the super keyword to call the implementation of its super class functions and attribute accessors:
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 fun addSize() { super.addSize() print("Kotlin2") } }
You can access the superclass of an external class in an internal class by using the super keyword defined by the external Class Name:super@Outer:
Class Bar: Foo () {override fun f (){/*...... * //} Override val x: Int get () = 0 inner class Baz {fun g () {super@Bar.f () // call f () println (super@Bar.x) implemented by Foo) // use the getter of x implemented by Foo }}}
Overwrite rules
In Kotlin, implementation inheritance is stipulated by the following rules: If a class inherits multiple implementations of the same Member from its direct superclass, it must overwrite this member and provide its own implementation (maybe one of them inherited ). To indicate the implementation from which the super type is inherited, we use the super defined by the type name in angle brackets. For example:super
:
open class Kotlin1{ open fun addSize(){}}interface A { fun addSize(){ println("aa") }}class Kotlin2 : Kotlin1("music",20,20),A { override fun addSize() { super .addSize() super.addSize() }}
It is okay to inherit Kotlin1 and A at the same time, but addSize () is inherited by Kotlin2. Therefore, we must overwrite addSize () in Kotlin2 and provide our own implementation to eliminate ambiguity.
Abstract class
Class and some of its members can be declared as abstract. Abstract members do not need to be implemented in this class. Note that we do not need to mark an abstract class fire function with open-because this is self-evident.
We can use an abstract member to overwrite a non-Abstract open member.
open class Base { open fun f() {} } abstract class Derived : Base() { override abstract fun f() }
Companion object
Unlike Java or C #, there is no static method for classes in Kotlin. In most cases, it is recommended that you simply use a package-level function.
If you need to write a function that does not need to be called by an instance of a class, but requires a function (such as a factory method) within the class, you can write it as a member of the object declaration in the class.
More specifically, if an associated object is declared inside your class, you can use the same syntax as calling static methods in Java/C # to call its members, use only the class name as the qualifier.