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

Kotlin中修改内联类构造器传入参数的最简方案

优雅实现Kotlin内联类Trimmed,确保字符串始终已修剪

我希望在Kotlin中通过内联类(inline class)实现一个包装String的Trimmed值类,要求所有实例的字符串都满足s == s.trim()。

最初尝试的直接写法无法运行:

@JvmInline
value class Trimmed private constructor(val str: String) {
    constructor(s : String) : super(s.trim()) // 写法无效
}

包括this(s.trim())在内的其他直接修改方式也都不生效。

这个问题的核心限制有这些:

  • Kotlin没有便捷方式让内联类的主构造器过滤或修改传入的字符串
  • 主构造器设为私有后,无法声明另一个签名完全相同(接收单个String参数)的构造器
  • 普通类可以在init块中修改属性值,但内联类不允许这么做(且String本身不可变,无法直接修改str的内容)
  • 尝试在同一文件中定义同名工厂函数,但无法访问私有构造器
  • 在伴生对象中定义同名工厂函数时,Kotlin会默认解析为递归调用自身,而非类构造器,只能通过文件私有typealias绕开,但这种方式不够优雅:
typealias Trimmed2 = Trimmed
@JvmInline
value class Trimmed private constructor(val str: String) {
    init { assert(str == str.trim()) }
    companion object {
        // Kotlin不允许在伴生对象内定义typealias
        fun Trimmed(s: String): Trimmed = Trimmed2(s.trim()) // 避免递归调用
    }
}

另一种可行但不够优雅的方案是使用带哑元参数的私有构造器,不过需要添加抑制未使用参数的注解:

@JvmInline
value class Trimmed private constructor(val str: String) {
    private constructor (untrimmed: String, @Suppress("UNUSED_PARAMETER") dummy: Unit) : this(untrimmed.trim())
    init { assert(str == str.trim()) }
    companion object {
        fun Trimmed(s: String): Trimmed = Trimmed(s, Unit)
    }
}

有没有更简洁优雅的实现方式?比如通过语法明确告知Kotlin,伴生函数要调用的是类构造器而非自身,从而无需使用哑元参数?

需求目标

  • 外部代码必须能以普通类的方式构造实例:Trimmed("abc"),不能使用of/trimmedOf这类命名的工厂函数或其他替代语法
  • 绝对不能构造出包含未修剪字符串的实例,外部代码和Trimmed类自身都能完全信任str始终是已修剪的状态

内容的提问来源于stack exchange,提问作者Some Guy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 00:56:09