


Chapter 4 Class and Object-Oriented Programming Chapter 4 Class and Object-Oriented Programming
Chapter 4 Class and Object Oriented Programming
In the previous chapters, we learned about Kotlin's basic language knowledge, type system and other related knowledge. In this chapter and the next chapter, we will learn Kotlin's support for object-oriented programming and functional programming.
In this chapter, we introduce Kotlin's object-oriented programming.
4.1 A brief history of object-oriented programmingIn the late 1950s, when writing large programs in the FORTRAN language, since there was no encapsulation mechanism, the variables at that time were all "global variables", so variable name conflicts would inevitably occur frequently. In ALGOL60, a program block identified by Begin - End is used to make the variable names in the block be local to avoid them from conflicting with variables with the same name outside the block in the program. For the first time in programming languages, the mechanism of encapsulation (protection) is provided. Since then, program block structure has been widely used in high-level languages such as Pascal, Ada, and C.
In the mid-to-late 1960s, Simula language was developed based on ALGOL. It developed the concept of ALGOL's block structure one step forward, proposed the concept of object, and used classes, which also supported class inheritance. A brief history of subsequent developments is shown in the figure below:

A brief history of object-oriented development
Alan Kay is one of the inventors of Smalltalk's object-oriented programming language and one of the founders of object-oriented programming ideas. He is also the earliest conceiver of laptops and an architect of modern Windows GUIs. Aaron Kay was the first to propose the concept of PC and the Internet, so people respectfully called him the "Master of Prophecy". He is one of the few technical geniuses in the IT industry today.
Object-oriented programming ideas are mainly reusability and flexibility (elasticity). Reusability is a major mechanism of object-oriented programming. Flexibility is mainly a characteristic of responding to changes, because customer needs are constantly changing. How to adapt to changes in customer needs is a problem of software design flexibility or flexibility.
Java is an object-oriented programming language, based on Smalltalk language, as an OOP language, it has the following five basic features:
1. Everything is an object, and each object stores data and can perform operations on itself. Therefore, each object contains two parts: member variables and member methods. The value of a member variable can be changed in a member method.
2. Programs are collections of objects. They inform each other of what they want to do by sending messages, that is, calling the corresponding member functions.
3. Each object has its own storage composed of other objects, which means that when creating a new object, you can use existing objects in member variables.
4. Each object has its type, and each object is an instance of a certain class. The characteristic that distinguishes each class from other classes is what type of message it can send, that is, which member functions it defines.
5. All objects of a certain type can accept the same message. Another description of an object is that the object has state (data, member variables), behavior (operation, member method) and identity (member name, memory address).
Object-oriented language is actually an abstraction of real objects in real life.
The requests (messages) that each object can accept are defined by the object's interface, and in the program, it must be composed of code that satisfies these requests, which is called the implementation of this interface. When sending a message (request) to an object, the object knows the purpose of the message (the implementation of the method is defined) and then executes the corresponding code.
We often say that some code snippets are elegant or beautiful, which actually means that they are more easily processed by human limited thinking.
For program compounding, a good code is that its surface area grows slowly than its volume.
The "surface area" of a code block is the information we need when we compound the code block (definition of the interface API protocol). The "volume" of the code block is the implementation logic inside the interface (the implementation code behind the API).
In object-oriented programming, an ideal object should only expose its abstract interface (pure surface, no volume), and its method plays the role of arrows. If you want to understand how one object reconciles with other objects, when you find that you have to dig deep into the implementation of the object, the original advantages of the programming paradigm you are using will disappear.
Object-oriented programming is a programming idea. Compared with early structured programming, the abstraction level is higher, and the way of thinking and solving problems is closer to the human way of thinking. Modern programming languages basically support object-oriented programming paradigm.
All problems in the computer field can be solved by abstract encapsulation to the upper layer. The essential concept of encapsulation here is actually "mapping". From process-oriented to object-oriented, to design patterns, architectural design, service-oriented, Sass/Pass/Iass, etc., there are many different ideas for software theory, but they will never leave their roots.
What kind of problem do you want to solve? What is your problem area? What is your model (data structure)? What is your algorithm? What is your understanding of the essence of this world? What are the logical problems in your business area, what are the processes? etc.Object-oriented programming thinks about things (objects) in the real world as the center, understands problems, and abstracts them into classes in the system based on the essential characteristics of these things. Its core idea can be briefly explained in the figure below:

Object-Oriented Programming
Object-oriented programming is based on class programming and is closer to human habitual methods of solving problems. Make the software world more like the real world. Object-oriented programming decomposes the system by abstracting key problem domains. Objects can not only represent concrete things, but also abstract rules, plans or events. The core concepts of object-oriented programming are shown in the following figure

The core concept of object-oriented programming
4.2 Declaration ClassThis section introduces the declarations of classes and constructors in Kotlin.
4.2.1 Empty ClassUse the class keyword to declare the class. We can declare a class that does nothing
Code language: javascript Number of code runs: 0 run copy<code class="javascript">class AnEmptyClassfun main(args: Array<String> ) { val anEmptyClass = AnEmptyClass() // Kotlin中不需要使用new println(anEmptyClass) println(anEmptyClass is AnEmptyClass) // 对象实例是AnEmptyClass类型println(anEmptyClass::class)}</code>
Output
Code language: javascript Number of code runs: 0 run copy<code class="javascript">com.easy.kotlin.AnEmptyClass@2626b418trueclass com.easy.kotlin.AnEmptyClass (Kotlin reflection is not available)</code>
In Kotlin, we can declare the constructor at the same time when declaring the class. The syntax format is to use brackets to include the parameter list of the constructor after the class.
Code language: javascript Number of code runs: 0 run copy<code class="javascript">class Person(var name: String, var age: Int, var sex: String) { // 声明类和构造函数override fun toString(): String { // override关键字,重写toString() return "Person(name='$name', age=$age, sex='$sex')" }}</code>
Using such a concise syntax, the attribute can be defined and the attribute value can be initialized through the main constructor (the attribute value can be var or val).
Use Person class in code like this
Code language: javascript Number of code runs: 0 run copy<code class="javascript">val person = Person("Jack", 29, "M")println("person = ${person}")</code>
Output
Code language: javascript Number of code runs: 0 run copy<code class="javascript">person = Person(name='Jack', age=29, sex='M')</code>
In addition, we can declare the attribute first, and then initialize the attribute value when constructing the instance object. Then our Person class can be declared as follows
Code language: javascript Number of code runs: 0 run copy<code class="javascript">class Person1 { lateinit var name: String // lateinit 关键字表示该属性延迟初始化var age: Int = 0 // lateinit 关键字不能修饰primitive 类型lateinit var sex: String override fun toString(): String { return "Person1(name='$name', age=$age, sex='$sex')" }}</code>
We can create a Person1 instance object in the code like this
Code language: javascript Number of code runs: 0 run copy<code class="javascript"> val person1 = Person1() person1.name = "Jack" person1.age = 29 person1.sex = "M" println("person1 = ${person1}")</code>
Output
Code language: javascript Number of code runs: 0 run copy<code class="javascript">person1 = Person1(name='Jack', age=29, sex='M')</code>
If we want to declare a class with multiple constructor methods, we can declare the constructor function using the constructor keyword. The example code is as follows
Code language: javascript Number of code runs: 0 run copy<code class="javascript">class Person2() { // 无参的主构造函数lateinit var name: String var age: Int = 0 lateinit var sex: String constructor(name: String) : this() { // this 关键字指向当前类对象实例this.name = name } constructor(name: String, age: Int) : this(name) { this.name = name this.age = age } constructor(name: String, age: Int, sex: String) : this(name, age) { this.name = name this.age = age this.sex = sex } override fun toString(): String { return "Person1(name='$name', age=$age, sex='$sex')" }}</code>
Overall, there are some boilerplate codes. In fact, in IDEA, when we write the above code, we only need to write the following 3 lines, and the rest will be automatically generated by IDEA.
Code language: javascript Number of code runs: 0 run copy<code class="javascript">class Person2 { lateinit var name: String var age: Int = 0 lateinit var sex: String}</code>
Automatically generate constructor operation diagram
1. "Right-click" the mouse operation in the current class and select Generate (the shortcut key on the Mac is Command N)

Right-click the mouse operation
After clicking, the dialog box pops up: Generate secondary constructor
Select Generate
Select the constructor parameters
Generate secondary constructors
Select the corresponding attribute and click OK to generate it.
No attribute is selected, generate
Code language: javascript Number of code runs: 0 run copy<code class="javascript">constructor()</code>
Select a name attribute to generate
Code language: javascript Number of code runs: 0 run copy<code class="javascript"> constructor(name: String) { this.name = name }</code>
Select name, age attribute generation
Code language: javascript Number of code runs: 0 run copy<code class="javascript"> constructor(name: String, age: Int) : this(name) { this.name = name this.age = age }</code>
Select all 3 attributes to generate
Code language: javascript Number of code runs: 0 run copy<code class="javascript"> constructor(name: String, age: Int, sex: String) : this(name, age) { this.name = name this.age = age this.sex = sex }</code>
Finally, we can create a Person2 instance object in the code like this
Code language: javascript Number of code runs: 0 run copy<code class="javascript"> val person21 = Person2() person21.name = "Jack" person21.age = 29 person21.sex = "M" println("person21 = ${person21}") val person22 = Person2("Jack", 29) person22.sex = "M" println("person22 = ${person22}") val person23 = Person2("Jack", 29, "M") println("person23 = ${person23}")</code>
In fact, the constructor we use the most in programming practice is this
Code language: javascript Number of code runs: 0 run copy<code class="javascript">class Person(var name: String, var age: Int, var sex: String)</code>
When it is really necessary to build an object through more complex logic, it can be implemented using the Builder mode.
4.3 Abstract classes and interfacesAbstract classes represent the relationship of "is-a", while interfaces represent the relationship of "has-a".
Abstract classes are used to represent abstract concepts in problem areas. All programming languages provide abstract mechanisms. Machine language is an imitation abstract of machines, assembly language is a high-level abstraction of machine language, and high-level languages (Fortran, C, Basic, etc.) are a high-level abstraction of assembly. The object-oriented programming language we are talking about here is a high-level encapsulation of procedural functions. This process is shown in the figure below

Abstract mechanism of programming languages
Abstract classes and interfaces are two different abstract concepts in the Kotlin language, and their existence provides very good support for polymorphism. This mechanism is the same as Java.
4.3.1 Abstract classes and abstract membersAbstraction is relative to concreteness. For example, designing a graphic editing software, there are specific concepts such as rectangle, circle, triangle, etc. in the problem area, and they are concrete. But they all belong to the abstract concept of shape (Shape). Their relationship is shown in the figure below

Abstract inheritance relationship of shape Shape
The corresponding Kotlin code is as follows
Code language: javascript Number of code runs: 0 run copy<code class="javascript">package com.easy.kotlinabstract class Shapeclass Rectangle : Shape() // 继承类的语法是使用冒号: , 父类需要在这里使用构造函数初始化class Circle : Shape()class Triangle : Shape()</code>
Because abstract concepts do not have corresponding specific concepts in the problem area, abstract classes cannot be instantiated. The following code compiler will report an error
Code language: javascript Number of code runs: 0 run copy<code class="javascript">val s = Shape() // 编译不通过!不能实例化抽象类</code>
We can only instantiate its inherited subclass. The code example is as follows
Code language: javascript Number of code runs: 0 run copy<code class="javascript">val r = Rectangle()println(r is Shape) // true</code>
Now we have abstract classes, but no members. Usually, members of a class have properties and functions. Members of abstract classes must also be abstract and need to be modified using the abstract keyword. Below we declare an abstract class Shape with width , heigth , radius attributes and area() function. The code is as follows
Code language: javascript Number of code runs: 0 run copy<code class="javascript">abstract class Shape { abstract var width: Double abstract var heigth: Double abstract var radius: Double abstract fun area(): Double}</code>
At this time, the method of inheriting the abstract class Shape is as follows
Code language: javascript Number of code runs: 0 run copy<code class="javascript">class Rectangle(override var width: Double, override var heigth: Double, override var radius: Double) : Shape() { // 声明类的同时也声明了构造函数override fun area(): Double { return heigth * width }}class Circle(override var width: Double, override var heigth: Double, override var radius: Double) : Shape() { override fun area(): Double { return 3.14 * radius * radius }}</code>
Among them, override is the keyword that overrides the parent class attributes and functions.
In the code, call the function of the specific implemented class
Code language: javascript Number of code runs: 0 run copy<code class="javascript">fun main(args: Array<String> ) { val r = Rectangle(3.0, 4.0, 0.0) println(r.area()) // 12.0 val c = Circle(0.0, 0.0, 4.0) println(c.area()) // 50.24}</code>
There can be functions with implementation in abstract classes. For example, we add a function onClick() to the abstract class Shape.
Code language: javascript Number of code runs: 0 run copy<code class="javascript">abstract class Shape { ... fun onClick() { // 默认是final的,不可被覆盖重写println("I am Clicked!") }}</code>
Then, we can directly call the onClick() function in all subclasses
Code language: javascript Number of code runs: 0 run copy<code class="javascript"> val r = Rectangle(3.0, 4.0, 0.0) r.onClick() // I am Clicked! val c = Circle(0.0, 0.0, 4.0) c.onClick() // I am Clicked!</code>
The onClick() function in the parent class Shape is final by default and cannot be overridden and rewritten. If you want to open the function to reimplement the subclass, we can prefix it with the open keyword
Code language: javascript Number of code runs: 0 run copy<code class="javascript">abstract class Shape { ... open fun onClick() { println("I am Clicked!") }}</code>
Override override in subclasses
Code language: javascript Number of code runs: 0 run copy<code class="javascript">class Rectangle(override var width: Double, override var heigth: Double, override var radius: Double) : Shape() { override fun area(): Double { return heigth * width } override fun onClick(){ println("${this::class.simpleName} is Clicked!") }}fun main(args: Array<String> ) { val r = Rectangle(3.0, 4.0, 0.0) println(r.area()) r.onClick()}</code>
Among them, this::class.simpleName is the reflection API in Kotlin. In the build.gradle of the Gradle project, we need to add the dependency compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" , which we will introduce in detail in the following chapters.
The above code runs the output
Code language: javascript Number of code runs: 0 run copy<code class="javascript">12.0Rectangle is Clicked!</code>
When a child class inherits a certain class, member variables in the parent class can be used, but not all member variables of the parent class are fully inherited. The specific principles are as follows:
1. Can inherit public and protected member variables of the parent class; cannot inherit private member variables of the parent class;
2. For the package access permission member variable of the parent class, if the subclass and the parent class are in the same package, the subclass can be inherited; otherwise, the subclass cannot be inherited;
3. For parent class member variables that can be inherited by subclasses, if a member variable with the same name appears in the subclass, a hidden phenomenon will occur, that is, the member variables of the subclass will block the member variables of the parent class with the same name. If you want to access the member variable of the same name in the parent class in the subclass, you need to use the super keyword to reference it.
4.3.2 InterfaceAn interface is a "class" that is more abstract than an abstract class. The interface itself represents a concept of "type". But at the syntax level, an interface itself is not a class, and it cannot instantiate an interface, we can only instantiate its implementation class.
Interfaces are used to establish protocols between classes. The implementation class that implements this interface must implement all methods of the interface. In Java 8 and Kotlin, interfaces can implement some common methods.
Interfaces are extensions of abstract classes. Like Java, Kotlin does not support inheriting multiple parent classes at the same time, which means that inheritance can only have one parent class (single inheritance). However, interfaces are different. A class can implement multiple interfaces at the same time (multiple combinations), regardless of whether there is any relationship between these interfaces. This allows multiple inheritance to be achieved.
Similar to Java, Kotlin uses interface as the keyword for the interface:
Code language: javascript Number of code runs: 0 run copy<code class="javascript">interface ProjectService</code>
Kotlin's interface is similar to that of Java 8. Compared with abstract classes, they can all include abstract methods and method implementations:
Code language: javascript Number of code runs: 0 run copy<code class="javascript">interface ProjectService { val name: String val owner: String fun save(project: Project) fun print() { println("I am project") }}</code>
There is no constructor for the interface. We use the colon :
syntax to implement an interface, if there are multiple uses ,
commas are separated:
<code class="javascript">class ProjectServiceImpl : ProjectService // 跟继承抽象类语法一样,使用冒号class ProjectMilestoneServiceImpl : ProjectService, MilestoneService // 实现多个接口使用逗号( ,) 隔开</code>
When rewriting print()
function, because the ProjectService and MilestoneService we implement have a print()
function, when we use super.print()
directly, the compiler cannot know that the print function we want to call. We call this: overwrite conflict, as shown in the figure below

Coverage conflicts
At this time, we can use the following syntax to call:
Code language: javascript Number of code runs: 0 run copy<code class="javascript">super<ProjectService> .print()super<MilestoneService> .print()</code>
Singleton mode is very commonly used. It is a commonly used software design pattern. For example, the default bean in Spring is a singleton. Through the singleton mode, you can ensure that there is only one instance of a class in the system. That is, a class has only one object instance.
There are no static properties and methods in Kotlin, but an object singleton object can be declared using the keyword object
:
<code class="javascript">package com.easy.kotlinobject User { val username: String = "admin" val password: String = "admin" fun hello() { println("Hello, object !") }}fun main(args: Array<String> ) { println(User.username) // 跟Java的静态类一样的调用形式println(User.password) User.hello()}</code>
Kotlin also provides companion objects, declared using the companion object
keyword:
<code class="javascript">class DataProcessor { companion object DataProcessor { fun process() { println("I am processing data ...") } }}fun main(args: Array<String> ) { DataProcessor.process() // I am processing data ...}</code>
A class can only have 1 companion object.
4.5 Data ClassAs the name suggests, a data class is a class that only stores data and does not contain operational behavior. Kotlin's data class can save us a lot of boilerplate code (Java forces us to write a bunch of getters and setters, but in fact these methods are "self-explanatory"), so that the final code is easier to understand and easy to maintain.
Use the keyword to create a class that contains only data:
Code language: javascript Number of code runs: 0 run copy<code class="javascript">data class LoginUser(val username: String, val password: String)</code>
A convenient Kotlin toolbox is provided in IDEA, and we can decompile the above code into equivalent Java code. The steps are as follows
1. Menu bar selection: Tools -> Kotlin -> Show Kotlin Bytecode

Menu bar selection: Tools -> Kotlin -> Show Kotlin Bytecode
Click Decompile
Click Decompile
Decompiled Java code
Decompiled Java code
The complete Java code after decompilation is
Code language: javascript Number of code runs: 0 run copy<code class="javascript">public final class LoginUser { @NotNull private final String username; @NotNull private final String password; @NotNull public final String getUsername() { return this.username; } @NotNull public final String getPassword() { return this.password; } public LoginUser(@NotNull String username, @NotNull String password) { Intrinsics.checkParameterIsNotNull(username, "username"); Intrinsics.checkParameterIsNotNull(password, "password"); super(); this.username = username; this.password = password; } @NotNull public final String component1() { return this.username; } @NotNull public final String component2() { return this.password; } @NotNull public final LoginUser copy(@NotNull String username, @NotNull String password) { Intrinsics.checkParameterIsNotNull(username, "username"); Intrinsics.checkParameterIsNotNull(password, "password"); return new LoginUser(username, password); } // $FF: synthetic method // $FF: bridge method @NotNull public static LoginUser copy$default(LoginUser var0, String var1, String var2, int var3, Object var4) { if ((var3 & 1) != 0) { var1 = var0.username; } if ((var3 & 2) != 0) { var2 = var0.password; } return var0.copy(var1, var2); } public String toString() { return "LoginUser(username=" this.username ", password=" this.password ")"; } public int hashCode() { return (this.username != null ? this.username.hashCode() : 0) * 31 (this.password != null ? this.password.hashCode() : 0); } public boolean equals(Object var1) { if (this != var1) { if (var1 instanceof LoginUser) { LoginUser var2 = (LoginUser)var1; if (Intrinsics.areEqual(this.username, var2.username) && Intrinsics.areEqual(this.password, var2.password)) { return true; } } return false; } else { return true; } }}</code>
The compiler will automatically create the following functions from the properties declared in the main constructor:
equals() / hashCode() function toString() format is "LoginUser(username=" this.username ", password=" this.password ")"component1(), component2() function returns the attribute value of the corresponding subscript, and arranges copy() in the order of declaration. Function: Renew the old object attributes LoginUser(username, password) An object is outIf these functions are already explicitly defined in the class, or inherited from the superclass, the compiler will no longer be generated.
Data classes have the following restrictions:
The main constructor contains at least one parameter parameter must be identified as val or var cannot be abstract, open, sealed or inner cannot inherit other classes (but can implement interfaces)Additionally, data classes can be used in deconstruction declarations:
Code language: javascript Number of code runs: 0 run copy<code class="javascript">package com.easy.kotlindata class LoginUser(val username: String, val password: String)fun main(args: Array<String> ) { val loginUser = LoginUser("admin", "admin") val (username, password) = loginUser println("username = ${username}, password = ${password}") // username = admin, password = admin}</code>
The Kotlin standard library provides Pair and Triple data classes.
4.6 NotesAnnotation is to append metadata to the code. Metadata information is defined by the annotation kotlin.Metadata.
Code language: javascript Number of code runs: 0 run copy<code class="javascript">@Retention(AnnotationRetention.RUNTIME)@Target(AnnotationTarget.CLASS)internal annotation class Metadata</code>
This @Metadata information exists in all class files generated by the Kotlin compiler and is read by the compiler and reflection. For example, we declare an annotation using Kotlin
Code language: javascript Number of code runs: 0 run copy<code class="javascript">annotation class Suspendable // Java中使用的是@interface Suspendable</code>
Then, the compiler will generate the corresponding metadata information
Code language: javascript Number of code runs: 0 run copy<code class="javascript">@Retention(RetentionPolicy.RUNTIME)@Metadata( mv = {1, 1, 7}, bv = {1, 0, 2}, k = 1, d1 = {"\u0000\n\n\u0002\u0018\u0002\n\u0002\u0010\u001b\n\u0000\b\u0086\u0002\u0018\u00002\u00020\u0001B\u0000¨\u0006\u0002"}, d2 = {"Lcom/easy/kotlin/Suspendable;", "", "production sources for module kotlin_tutorials_main"})public @interface Suspendable {}</code>
Kotlin's annotations are fully compatible with Java's annotations. For example, we use Spring Data Jpa in Kotlin
Code language: javascript Number of code runs: 0 run copy<code class="javascript">interface ImageRepository : PagingAndSortingRepository<Image, Long> { @Query("SELECT a from #{#entityName} a where a.isDeleted=0 and a.isFavorite=1 and a.category like %:searchText% order by a.gmtModified desc") fun searchFavorite(@Param("searchText") searchText: String, pageable: Pageable): Page<Image> @Throws(Exception::class) @Modifying @Transactional @Query("update #{#entityName} a set a.isFavorite=1,a.gmtModified=now() where a.id=?1") fun addFavorite(id: Long)}</code>
It's basically the same as Java's annotations. Another example of code that Kotlin uses Spring MVC annotations
Code language: javascript Number of code runs: 0 run copy<code class="javascript">@Controllerclass MeituController { @Autowired lateinit var imageRepository: ImageRepository @RequestMapping(value = *arrayOf("/", "meituView"), method = arrayOf(RequestMethod.GET)) fun meituView(model: Model, request: HttpServletRequest): ModelAndView { model.addAttribute("requestURI", request.requestURI) return ModelAndView("meituView") }}</code>
From the above example, we can see that Kotlin uses Java frameworks very simple and convenient.
4.7 EnumerationIn Kotlin, the enum class keyword is used to declare an enum class. For example
Code language: javascript Number of code runs: 0 run copy<code class="javascript">enum class Direction { NORTH, SOUTH, WEST, EAST // 每个枚举常量都是一个对象, 用逗号分隔}</code>
Compared with string constants, type safety can be achieved using enumerations. The enumeration class has two built-in properties:
Code language: javascript Number of code runs: 0 run copy<code class="javascript"> public final val name: String public final val ordinal: Int</code>
They represent the value and subscript positions of the enumeration object respectively. For example, the information of its enumeration object is as follows
Code language: javascript Number of code runs: 0 run copy<code class="javascript">>>> val north = Direction.NORTH>>> north.nameNORTH>>> north.ordinal0>>> north is Directiontrue</code>
Each enum is an instance of the enum class, and they can be initialized:
Code language: javascript Number of code runs: 0 run copy<code class="javascript">enum class Color(val rgb: Int) { RED(0xFF0000), GREEN(0x00FF00), BLUE(0x0000FF)}</code>
The information about the enumeration object of the enumeration color is as follows
Code language: javascript Number of code runs: 0 run copy<code class="javascript">>>> val c = Color.GREEN>>> cGREEN>>> c.rgb65280>>> c.ordinal1>>> c.nameGREEN</code>
In Kotlin, classes can be nested. One class can be nested in other classes and can be nested with multiple layers.
Code language: javascript Number of code runs: 0 run copy<code class="javascript">class NestedClassesDemo { class Outer { private val zero: Int = 0 val one: Int = 1 class Nested { fun getTwo() = 2 class Nested1 { val three = 3 fun getFour() = 4 } } }}</code>
Test code:
Code language: javascript Number of code runs: 0 run copy<code class="javascript"> val one = NestedClassesDemo.Outer().one val two = NestedClassesDemo.Outer.Nested().getTwo() val three = NestedClassesDemo.Outer.Nested.Nested1().three val four = NestedClassesDemo.Outer.Nested.Nested1().getFour()</code>
We can see that the way NestedClassesDemo.Outer.Nested().getTwo() in the code accesses nested classes is to directly use类名.
The number of layers of nested are used to access them.
Ordinary nested classes do not hold references to external classes, so they cannot access variables of external classes:
Code language: javascript Number of code runs: 0 run copy<code class="javascript">class NestedClassesDemo {class Outer { private val zero: Int = 0 val one: Int = 1 class Nested { fun getTwo() = 2 fun accessOuter() = { println(zero) // error, cannot access outer class println(one) // error, cannot access outer class } }}}</code>
If a class Inner wants to access members of the external class Outer, you can add a modifier inner before this class. The inner class will have a reference to the object of the outer class:
Code language: javascript Number of code runs: 0 run copy<code class="javascript">package com.easy.kotlinclass NestedClassesDemo { class Outer { private val zero: Int = 0 val one: Int = 1 inner class Inner { fun accessOuter() = { println(zero) // works println(one) // works } } }}fun main(args: Array<String> ) { val innerClass = NestedClassesDemo.Outer().Inner().accessOuter()}</code>
We can see that when accessing inner class Inner
, we use Outer().Inner()
, which is an object reference that holds Outer. It is distinguished from the method of using class names to access it directly.
Anonymous inner class is an inner class without a name. Since it is an inner class, it can naturally access variables of the outer class.
We use object expressions to create an anonymous internal class instance:
Code language: javascript Number of code runs: 0 run copy<code class="javascript">class NestedClassesDemo { class AnonymousInnerClassDemo { var isRunning = false fun doRun() { Thread(object : Runnable { // 匿名内部类override fun run() { isRunning = true println("doRun : i am running, isRunning = $isRunning") } }).start() } }}</code>
If the object is a functional Java interface, that is, an instance of a Java interface with a single abstract method, such as the Runnable interface in the example above:
Code language: javascript Number of code runs: 0 run copy<code class="javascript">@FunctionalInterfacepublic interface Runnable { public abstract void run();}</code>
We can create it using lambda expressions, and the following writing methods are all possible:
Code language: javascript Number of code runs: 0 run copy<code class="javascript"> fun doStop() { var isRunning = true Thread({ isRunning = false println("doStop: i am not running, isRunning = $isRunning") }).start() } fun doWait() { var isRunning = true val wait = Runnable { isRunning = false println("doWait: i am waiting, isRunning = $isRunning") } Thread(wait).start() } fun doNotify() { var isRunning = true val wait = { isRunning = false println("doNotify: i notify, isRunning = $isRunning") } Thread(wait).start() }</code>
We will introduce more about Lambda expressions and functional programming in the next chapter.
Summary of this chapterIn this chapter, we introduce the characteristics of Kotlin object-oriented programming: classes and constructors, abstract classes and interfaces, inheritance and combination, and also introduce the characteristics of Kotlin, such as annotation classes, enumeration classes, data classes, nested classes, internal classes, anonymous internal classes, singleton object objects, etc.
In general, in terms of the support of the object-oriented programming paradigm, Kotlin has added a lot of interesting functions and features to Java, which makes our code more convenient and quick.
We know that in Java 8, support for functional programming was introduced: Lambda expressions, Function interfaces, stream APIs, etc., while in Kotlin, support for functional programming is more comprehensive and rich, and the code is more concise and elegant. In the next chapter, let’s learn Kotlin’s functional programming together.
The above is the detailed content of Chapter 4 Class and Object-Oriented Programming Chapter 4 Class and Object-Oriented Programming. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics











With the popularization and development of digital currency, more and more people are beginning to pay attention to and use digital currency apps. These applications provide users with a convenient way to manage and trade digital assets. So, what kind of software is a digital currency app? Let us have an in-depth understanding and take stock of the top ten digital currency apps in the world.

The built-in quantization tools on the exchange include: 1. Binance: Provides Binance Futures quantitative module, low handling fees, and supports AI-assisted transactions. 2. OKX (Ouyi): Supports multi-account management and intelligent order routing, and provides institutional-level risk control. The independent quantitative strategy platforms include: 3. 3Commas: drag-and-drop strategy generator, suitable for multi-platform hedging arbitrage. 4. Quadency: Professional-level algorithm strategy library, supporting customized risk thresholds. 5. Pionex: Built-in 16 preset strategy, low transaction fee. Vertical domain tools include: 6. Cryptohopper: cloud-based quantitative platform, supporting 150 technical indicators. 7. Bitsgap:

Recommended cryptocurrency trading platforms include: 1. Binance: the world's largest trading volume, supports 1,400 currencies, FCA and MAS certification. 2. OKX: Strong technical strength, supports 400 currencies, approved by the Hong Kong Securities Regulatory Commission. 3. Coinbase: The largest compliance platform in the United States, suitable for beginners, SEC and FinCEN supervision. 4. Kraken: a veteran European brand, ISO 27001 certified, holds a US MSB and UK FCA license. 5. Gate.io: The most complete currency (800), low transaction fees, and obtained a license from multiple countries. 6. Huobi Global: an old platform that provides a variety of services, and holds Japanese FSA and Hong Kong TCSP licenses. 7. KuCoin

This groundbreaking development will enable financial institutions to leverage the globally recognized ISO20022 standard to automate banking processes across different blockchain ecosystems. The Ease protocol is an enterprise-level blockchain platform designed to promote widespread adoption through easy-to-use methods. It announced today that it has successfully integrated the ISO20022 messaging standard and directly incorporated it into blockchain smart contracts. This development will enable financial institutions to easily automate banking processes in different blockchain ecosystems using the globally recognized ISO20022 standard, which is replacing the Swift messaging system. These features will be tried soon on "EaseTestnet". EaseProtocolArchitectDou

Ranking of the top ten formal virtual currency exchange apps in 2025: 1. OKX, 2. Binance, 3. Huobi, 4. Coinbase, 5. Kraken, 6. Bitfinex, 7. KuCoin, 8. Gemini, 9. Bitstamp, 10. Poloniex, each performs outstandingly in terms of security, user experience, transaction fees, liquidity, currency richness, professional tools, compliance, privacy protection, leveraged trading, degree of internationalization, customer service, etc.

The methods to download the Hong Kong Digital Currency Exchange APP include: 1. Select a compliant platform, such as OSL, HashKey or Binance HK, etc.; 2. Download through official channels, iOS users download on the App Store, Android users download through Google Play or official website; 3. Register and verify their identity, use Hong Kong mobile phone number or email address to upload identity and address certificates; 4. Set security measures, enable two-factor authentication and regularly check account activities.

The prospects of digital currency apps are broad, which are specifically reflected in: 1. Technology innovation-driven function upgrades, improving user experience through the integration of DeFi and NFT and AI and big data applications; 2. Regulatory compliance trends, global framework improvements and stricter requirements for AML and KYC; 3. Function diversification and service expansion, integrating lending, financial management and other services and optimizing user experience; 4. User base and global expansion, and the user scale is expected to exceed 1 billion in 2025.

The top 10 digital virtual currency trading platforms are: 1. Binance, 2. OKX, 3. Coinbase, 4. Kraken, 5. Huobi Global, 6. Bitfinex, 7. KuCoin, 8. Gemini, 9. Bitstamp, 10. Bittrex. These platforms all provide high security and a variety of trading options, suitable for different user needs.
