返回

深入探索Kotlin的面向对象编程世界(下)

后端

继承

继承是面向对象编程中最重要的特性之一。它允许你创建一个新类(子类),该类从另一个类(父类)继承属性和行为。这使得你可以轻松地创建新的类,而无需重复编写相同的代码。

class Person(val name: String, val age: Int)

class Student(name: String, age: Int, val major: String) : Person(name, age)

fun main() {
    val student = Student("Alice", 20, "Computer Science")
    println(student.name) // Alice
    println(student.age) // 20
    println(student.major) // Computer Science
}

在这个例子中,Student 类从 Person 类继承。这使得 Student 类具有 Person 类的所有属性和行为,还允许 Student 类定义自己的属性和行为。

属性

属性是对象的特征或状态。属性可以是只读的,也可以是可写的。

class Person(val name: String, var age: Int)

fun main() {
    val person = Person("Alice", 20)
    println(person.name) // Alice
    person.age = 21
    println(person.age) // 21
}

在这个例子中,Person 类具有两个属性:nameagename 属性是只读的,而 age 属性是可写的。

抽象类

抽象类是不能被实例化的类。抽象类可以包含抽象方法,抽象方法没有实现。子类必须实现抽象类中的所有抽象方法,才能被实例化。

abstract class Shape {
    abstract fun area(): Double
}

class Rectangle(val width: Double, val height: Double) : Shape() {
    override fun area(): Double {
        return width * height
    }
}

class Circle(val radius: Double) : Shape() {
    override fun area(): Double {
        return Math.PI * radius * radius
    }
}

fun main() {
    val rectangle = Rectangle(5.0, 10.0)
    println(rectangle.area()) // 50.0

    val circle = Circle(5.0)
    println(circle.area()) // 78.53981633974483
}

在这个例子中,Shape 类是一个抽象类,它包含一个抽象方法 area()Rectangle 类和 Circle 类是 Shape 类的子类,它们都实现了 area() 方法。

接口

接口是一个定义了方法签名的类。接口不能被实例化,但它可以被其他类实现。实现接口的类必须实现接口中定义的所有方法。

interface Drawable {
    fun draw()
}

class Rectangle(val width: Double, val height: Double) : Drawable {
    override fun draw() {
        println("Drawing a rectangle with width $width and height $height")
    }
}

class Circle(val radius: Double) : Drawable {
    override fun draw() {
        println("Drawing a circle with radius $radius")
    }
}

fun main() {
    val rectangle = Rectangle(5.0, 10.0)
    rectangle.draw() // Drawing a rectangle with width 5.0 and height 10.0

    val circle = Circle(5.0)
    circle.draw() // Drawing a circle with radius 5.0
}

在这个例子中,Drawable 接口定义了一个方法 draw()Rectangle 类和 Circle 类都实现了 Drawable 接口,并且都实现了 draw() 方法。

伴生对象

伴生对象是一个与类关联的对象。伴生对象可以包含与类相关的属性和方法。伴生对象可以使用类名来访问。

class Person(val name: String, val age: Int) {
    companion object {
        val DEFAULT_AGE = 18
    }

    fun getAge(): Int {
        return if (age == 0) DEFAULT_AGE else age
    }
}

fun main() {
    val person = Person("Alice", 0)
    println(person.getAge()) // 18

    val defaultAge = Person.DEFAULT_AGE
    println(defaultAge) // 18
}

在这个例子中,Person 类有一个伴生对象,它包含一个属性 DEFAULT_AGE 和一个方法 getAge()getAge() 方法使用 DEFAULT_AGE 属性作为默认值来返回对象的年龄。

密封类

密封类是一个受限的类,它只能被其嵌套类继承。密封类可以用来表示一组相关的类,并且可以防止创建不属于该组的类。

sealed class Shape {
    class Rectangle(val width: Double, val height: Double) : Shape()
    class Circle(val radius: Double) : Shape()
}

fun main() {
    val shape: Shape = Circle(5.0)

    when (shape) {
        is Rectangle -> println("Rectangle with width ${shape.width} and height ${shape.height}")
        is Circle -> println("Circle with radius ${shape.radius}")
    }
}

在这个例子中,Shape 类是一个密封类,它有两个嵌套类:Rectangle 类和 Circle 类。main() 函数创建了一个 Shape 类型的变量 shape,并将它设置为一个 Circle 对象。然后,when 语句用于根据 shape 的类型来执行不同的操作。

数据类

数据类是一种特殊的类,它提供了开箱即用的 toString()equals()hashCode() 方法。数据类还支持解构,这使得可以轻松地将数据类对象分解为其各个属性。

data class Person(val name: String, val age: Int)

fun main() {
    val person = Person("Alice", 20)

    println(person) // Person(name=Alice, age=20)

    val (name, age) = person

    println("$name is $age years old") // Alice is 20 years old
}

在这个例子中,Person 类是一个数据类。main() 函数创建了一个 Person 对象 person,并将其打印到控制台。然后,person 对象被解构为两个变量 nameage,并将其打印到控制台。

封装和多态

封装是将数据的表示与操作分离。多态是指父类和子类可以具有相同的方法名,但是这些方法在不同的子类中具有不同的实现。

abstract class Shape {
    abstract fun area(): Double
}

class Rectangle(val width: Double, val height: Double) : Shape() {
    override fun area(): Double {
        return width * height
    }
}

class Circle(val radius: Double) : Shape() {
    override fun area(): Double {
        return Math.PI * radius * radius
    }
}

fun main() {
    val shapes: List<Shape> = listOf(
        Rectangle(5.0, 10.0),
        Circle(5.0)
    )

    for (shape in shapes) {
        println(shape.area()) // 50.0, 78.53981633974483
    }
}

在这个例子中,Shape 类是一个抽象类,它包含一个抽象方法 area()Rectangle 类和 Circle 类都是 Shape 类的子类,它们都实现了 area() 方法。main() 函数创建了一个 Shape 类型的列表 shapes,并使用 for 循环来遍历该列表。在每个循环中,area() 方法都被调用来计算每个形状的面积。

委托

委托是一种在类中使用其他类的属性和方法的方式。委托类必须实现一个或多个接口,委托类中的属性和方法可以直接在委托类中使用。

interface Drawable {
    fun draw()
}

class Rectangle(val width: Double, val height: