You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何仅在类泛型类型满足条件时定义方法?

实现Event的subscribe重载需求

问题分析

你原来的写法无法编译,是因为Kotlin不支持在类成员函数上单独为类的泛型参数添加where约束(这种语法不符合Kotlin规范),直接在类内重载无法区分TPayload是否为Unit的场景。

解决方案:使用扩展函数实现针对性重载

我们可以通过扩展函数,给Event<Unit>单独添加无参数的subscribe重载,其他泛型类型的Event只会保留带参数的版本,完美匹配你的需求。

1. 定义基础Event类

先实现通用的Event类,包含带参数的核心订阅方法:

class Event<TPayload>() {
    private val handlers = mutableListOf<(TPayload) -> Unit>()

    // 通用带参数订阅方法
    fun subscribe(handler: (payload: TPayload) -> Unit) {
        handlers.add(handler)
    }

    // 触发事件的方法(可选,用于测试验证)
    fun trigger(payload: TPayload) {
        handlers.forEach { it(payload) }
    }
}

2. 添加Event专属的扩展重载

针对Event<Unit>编写扩展函数,重载subscribe方法:

// 仅对Event<Unit>生效的无参数订阅重载
fun Event<Unit>.subscribe(handler: () -> Unit) {
    // 内部复用通用订阅逻辑,忽略Unit参数
    this.subscribe { handler() }
}

3. 测试效果

fun main() {
    // Event<Unit> 拥有两个subscribe重载
    val unitEvent = Event<Unit>()
    unitEvent.subscribe { println("无参数订阅触发") }
    unitEvent.subscribe { _ -> println("带Unit参数的订阅触发") }
    unitEvent.trigger(Unit)

    // Event<String> 仅拥有带参数的subscribe
    val stringEvent = Event<String>()
    stringEvent.subscribe { str -> println("收到字符串:$str") }
    // 下面这行代码会编译报错,因为Event<String>没有无参数的subscribe重载
    // stringEvent.subscribe { println("这行编译不通过") }
    stringEvent.trigger("Kotlin")
}

原理说明

  • 扩展函数的接收者类型限定为Event<Unit>,因此只有该类型的实例能调用这个重载方法,其他泛型类型的Event看不到该扩展。
  • 扩展函数内部复用了通用的subscribe方法,避免重复实现逻辑,保证代码一致性。

内容的提问来源于stack exchange,提问作者Sod Almighty

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 09:55:24