1. 概述

本文将介绍如何在 Kotlin 的接口中定义 Companion Object,并解释其对实现类的影响。同时,我们还会展示如何通过 Companion Object 实现接口。内容通俗易懂,适合有一定 Kotlin 基础的开发者阅读。

2. 在接口中使用 Companion Object

在 Kotlin 中,接口中定义 Companion Object 的方式与类中完全一致。我们来看一个 Vehicle 接口的例子:

interface Vehicle {
    fun getNumberOfWheels(): Int

    companion object {
        const val DOUBLE_TRACK_AMOUNT_OF_WHEELS = 3
        fun isDoubleTrack(vehicle: Vehicle) = vehicle.getNumberOfWheels() > DOUBLE_TRACK_AMOUNT_OF_WHEELS
    }
}

这个 Companion Object 定义了一个常量 DOUBLE_TRACK_AMOUNT_OF_WHEELS 和一个工具方法 isDoubleTrack(),用于判断车辆是否为双轨类型(即轮子数量是否大于 3)。
常见使用场景:接口中 Companion Object 通常用于存放常量或工具方法

3. 实现包含 Companion Object 的接口

接口中的 Companion Object 不会影响接口的实现逻辑,也就是说它并不改变接口契约。它只是与接口绑定的一个“附属对象”,其本质是一个单例。

我们来看一个实现 Vehicle 接口的 Car 类:

class Car(val brand: String, val model: String, val age: Int) : Vehicle {

    companion object {
        const val ANTIQUE_CAR_MINIMAL_AGE = 30
    }

    override fun getNumberOfWheels() = 4
    fun isAntique() = age >= ANTIQUE_CAR_MINIMAL_AGE
}

可以看到,Car 类实现了 Vehicle 接口,并拥有自己的 Companion Object。这与接口中的 Companion Object 没有任何关系,各自独立存在。

4. 在 Companion Object 中实现接口

Kotlin 允许我们在 Companion Object 中直接实现接口。我们使用命名 Companion Object 来实现 Vehicle 接口:

class VehicleImplementedInCompanionObject {

    companion object Bicycle : Vehicle {
        override fun getNumberOfWheels(): Int {
            return 2
        }
    }
}

接口在类中实现 和 在 Companion Object 中实现,本质上没有区别

为了验证这一点,我们分别测试 CarBicycle 实例的 getNumberOfWheels() 方法调用:

测试 Car 实例

@Test
fun `given type implementing Vehicle, when use should work`() {
    val car = Car("Ford", "Mustang", 12)
    assertThat(car.getNumberOfWheels()).isEqualTo(4)
    assertThat(Vehicle.isDoubleTrack(car)).isTrue
}

测试 Bicycle 实例(Companion Object)

@Test
fun `given companion object implementing Vehicle, when use should work`() {
    val bicycle = VehicleImplementedInCompanionObject.Bicycle
    assertThat(bicycle.getNumberOfWheels()).isEqualTo(2)
    assertThat(Vehicle.isDoubleTrack(bicycle)).isFalse
}

⚠️ 注意:Car 可以创建多个实例,而 Bicycle 是单例,始终指向同一个对象。

5. 总结

本文我们学习了:

  • 如何在 Kotlin 接口中定义 Companion Object
  • Companion Object 不影响接口实现逻辑
  • 如何在 Companion Object 中实现接口
  • Companion Object 实现接口与类实现接口本质上没有区别

最终结论是:接口中 Companion Object 的存在不会改变接口契约,它主要用于定义常量和工具方法。接口的实现可以在类中,也可以在 Companion Object 中完成,使用方式一致。

完整示例代码请查看 GitHub 仓库


原始标题:Companion Objects in Kotlin Interfaces