Kotlin学习笔记(7)--类与对象

Kotlin 是一门面向对象的编程语言,支持类和对象的创建与管理。

类的定义

在 Kotlin 中,使用 class 关键字定义类。类可以包含构造函数、属性、方法、嵌套类等。

class Person {
    var name: String = ""
    var age: Int = 0

    fun greet() {
        println("Hello, my name is $name and I am $age years old.")
    }
}

注:如果一个类只有方法,没有具体的构造函数参数、初始化块或额外的成员声明,那么在定义类时可以省略花括号 {},例如:

class Person {
    fun greet() {
        println("Hello, my name is $name and I am $age years old.")
    }
}

实例化对象

要使用类,需要实例化它的对象:

val person = Person()
person.name = "Alice"
person.age = 25

构造器

类可以有主构造器和一个或多个次构造器。

主构造器

Kotlin 将构造函数直接集成在类定义中:

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

实例化

val person = Person("Alice", 25)

初始化代码块

init 块用于类的初始化时执行代码:

class Person(val name: String, var age: Int) {
    init {
        println("Person initialized with name: $name and age: $age")
    }
}

次构造器

如果类需要多个构造函数,可以定义次构造函数

class Person {
    var name: String
    var age: Int

    constructor(name: String) {
        this.name = name
        this.age = 0
    }

    constructor(name: String, age: Int) {
        this.name = name
        this.age = age
    }
}

fun main() {
    val person1 = Person("Alice")
    val person2 = Person("Bob", 30)
}

注意: 如果类有主构造器,则每个次构造器需要委托给主构造器。

class Rectangle(val width: Int, val height: Int) {
    constructor(size: Int) : this(size, size)
}

类的继承

Kotlin 中类默认是 final 的,需要加上 open 关键字才能被继承:

open class Animal {
    open fun sound() {
        println("Animal sound")
    }
}

class Dog : Animal() {
    override fun sound() {
        println("Dog barks")
    }
}

抽象类

抽象类是不能被实例化的类,通常用于定义接口和共享代码。

abstract class Animal(
    var name: String
) {
    init {
        println("这只动物的名字是 $name")
    }

    abstract fun makeSound()
}

class Dog : Animal("Dog") {
    override fun makeSound() {
        println("汪汪")
    }
}

class Cat : Animal("Cat") {
    override fun makeSound() {
        println("喵喵")
    }
}

fun main() {
    val dog = Dog()
    dog.makeSound() // 输出: 汪汪

    val cat = Cat()
    cat.makeSound() // 输出: 喵喵
}

嵌套类

嵌套类是在另一个类内部定义的类,但它不持有外部类的引用。

class Outer {
    private val bar = "外部类属性"

    class Nested {
        fun foo() = "嵌套类方法"
    }
}

fun main() {
    val nested = Outer.Nested()
    println(nested.foo()) // 输出: 嵌套类方法
}

内部类

内部类使用 inner 关键字声明,可以访问外部类的成员。

class Outer {
    private val bar = "外部类属性"

    inner class Inner {
        fun foo() = bar
    }
}

fun main() {
    val outer = Outer()
    val inner = outer.Inner()
    println(inner.foo()) // 输出: 外部类属性
}

匿名内部类

匿名内部类用于创建没有名称的类的实例,常用于实现接口或继承抽象类。

abstract class Animal(val name: String) {
    abstract fun makeSound()
}

fun main() {
    val bear = object : Animal("Bear") {
        override fun makeSound() {
            println("吼叫!")
        }
    }
    bear.makeSound() // 输出: 吼叫!
}

密封类

在密封类中,所有的子类都必须在密封类的同一个文件中定义。这种特性使得在处理不同类型的子类时更加安全和便捷,尤其适用于表示状态或结果的场景,如网络请求的成功与失败状态。

sealed class Result
class Success(val data: String) : Result()
class Failure(val error: String) : Result()

数据类

数据类用于存储数据,并自动生成常见的函数(equalshashCodetoString 等):

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

类的修饰符

Kotlin 支持多种修饰符,用于控制类的可见性和行为。

  • open:允许类被继承。默认情况下,类是 final 的,不能被继承。
  • abstract:声明一个抽象类,不能被实例化。
  • final:默认修饰符,类不能被继承。
  • sealed:限制类的继承范围,适用于表示受限的类层次结构。
  • data:用于数据类,自动生成 equals(), hashCode(), toString(), copy() 等方法。
  • enum:用于枚举类,表示固定的常量集合。

示例:

// 可继承的类
open class Vehicle(val make: String)

// 数据类
data class User(val name: String, val age: Int)

// 枚举类
enum class Direction {
    NORTH, SOUTH, EAST, WEST
}

接口

Kotlin 的接口(Interface)是定义一组方法和属性的蓝图,任何类都可以实现这些接口,从而确保类具备特定的行为和特性。接口在 Kotlin 中提供了一种灵活的方式来实现多重继承,并允许代码的高复用性和可维护性。

定义接口

在 Kotlin 中,使用 interface 关键字来定义接口。接口可以包含抽象方法、属性以及方法的默认实现。

interface Drivable {
    // 抽象属性
    val maxSpeed: Int

    // 抽象方法
    fun drive()

    // 有默认实现的方法
    fun brake() {
        println("The vehicle is braking.")
    }
}

实现接口

类通过冒号 : 来实现一个或多个接口。如果接口中有抽象成员,类需要提供这些成员的具体实现;对于有默认实现的方法,类可以选择重写它们,也可以直接使用默认实现。

class Car(override val maxSpeed: Int) : Drivable {
    override fun drive() {

对象

对象表达式

对象表达式用于创建匿名对象:

val obj = object {
    var x: Int = 10
    var y: Int = 20
}
println(obj.x + obj.y)  // 输出:30

对象声明

对象声明用于创建单例对象,类似于Java的静态类:

object Singleton {
    var name: String = "Singleton"
    fun printName() {
        println(name)
    }
}

调用

Singleton.printName()  // 输出:Singleton

伴生对象

Kotlin 中的伴生对象(Companion Object)是用于在类内部定义与类本身相关联的对象。它们提供了一种替代 Java 中静态成员的方式,使得在 Kotlin 中实现类似静态方法和属性的功能成为可能。

伴生对象的定义

使用 companion object 关键字用于声明一个伴生对象。每个类最多只能有一个伴生对象。伴生对象的成员可以通过类名直接访问,就像 Java 中的静态成员一样。

class MyClass {
    companion object {
        fun create(): MyClass = MyClass()
    }
}

MyClass 类有一个伴生对象,其中定义了一个 create 方法,用于创建 MyClass 的实例。

伴生对象的命名

默认情况下,伴生对象没有名称,但也可以为它指定一个名称:

class MyClass {
    companion object Factory {
        fun create(): MyClass = MyClass()
    }
}

通过给伴生对象命名(例如上面的 Factory),可以更明确地引用它:

val instance = MyClass.Factory.create()

如果没有命名,可以直接使用类名访问:

val instance = MyClass.create()

访问伴生对象的成员

伴生对象的成员可以像静态成员一样通过类名访问:

class MyClass {
    companion object {
        const val CONSTANT = "SomeConstant"

        fun printConstant() {
            println(CONSTANT)
        }
    }
}

fun main() {
    println(MyClass.CONSTANT)       // 输出: SomeConstant
    MyClass.printConstant()         // 输出: SomeConstant
}

使用伴生对象实现工厂模式

伴生对象常用于实现工厂模式,通过定义工厂方法来创建类的实例:

class User private constructor(val name: String) {
    companion object {
        fun create(name: String): User {
            // 可以在这里添加创建实例的逻辑,如验证、缓存等
            return User(name)
        }
    }
}

fun main() {
    val user = User.create("Alice")
    println(user.name)  // 输出: Alice
}

  • User 类的构造函数被声明为 private,这意味着外部无法直接创建实例。相反,必须通过伴生对象的 create 方法来创建 User 的实例。

伴生对象实现接口

伴生对象还可以实现接口

interface Factory<T> {
    fun create(): T
}

class MyClass {
    companion object : Factory<MyClass> {
        override fun create(): MyClass = MyClass()
    }
}

fun main() {
    val factory: Factory<MyClass> = MyClass
    val instance = factory.create()
}
  • 伴生对象实现了 Factory 接口,这使得它可以被用作工厂实例。

扩展伴生对象

还可以为伴生对象定义扩展函数和属性:

class MyClass {
    companion object
}

fun MyClass.Companion.greet() {
    println("Hello from companion object!")
}

fun main() {
    MyClass.greet()  // 输出: Hello from companion object!
}
posted @ 2024-10-21 10:49  Jacob-Chen  阅读(259)  评论(0)    收藏  举报