装箱字符串字段或扩展 Kotlin 中的所有字符串的替代方法?

Alternatives to boxing string field or extending ALL strings in Kotlin?

鉴于无法在 Kotlin 中子class 内置类型,我正在寻找一种方法来向 特定类型的字符串字段 添加特殊方法功能在记录中,而不将这些扩展函数应用于 所有字符串(即使在该记录类型中)。比方说,我在记录中有一些可变字符串字段,我想为其定义特殊用途的行为。

class Customer {
  // ...
  var zipcode: String
  var email: String
  // ...
}

我的目标是:

  1. 避免将 zipcode 装箱成 class Zipcode 的运行时开销 考虑到客户记录集的大小可能是数百万,内部只有一个 var。
  2. 避免必须赋值的语法 thisCustomer.zipcode.value = "99999-9999"thisCustomer.zipcode = Zipcode("99999-9999"),如果我最终不得不将字符串装箱。
  3. 避免添加通用 String.plusFourString.domain 扩展属性,即使只是在客户中 class... 因为邮政编码和电子邮件在技术上可以互相调用 扩展

我一直在考虑这个问题并考虑了以下选项,但每一个都被删除了:

我是否遗漏了一个明显的解决方案?即使不是很明显,利用 Kotlin 的所有语法魔法,有没有办法让它发生?也许有一种方法可以在不使用这些方法的情况下实现上述 some/all 的目标?

您可以使用委托创建装饰器class:

class YourString(val value: String) : Comparable<String> by value, CharSequence by value {

    val plusFour: String
        get() = ""  //your logic here

    val domain: String
        get() = ""  //your logic here

    override fun toString() = value
}

用法:

fun String.toYourString() = YourString(this)

class Customer(var zipCode: YourString, var email: YourString)

val customer = Customer("+4 99999-9999".toYourString(), "xxx@company.com".toYourString())
println(customer.zipCode.plusFour)
println(customer.email.domain)

可以用type aliases来表达意思:

typealias ZipCode = String
val ZipCode.plusFour get() = ...

typealias Email = String
val Email.domain get() = ...

class Customer {
  // ...
  var zipcode: ZipCode
  var email: Email
  // ...
}

不幸的是,这 阐明了意图,并没有阻止编译器允许 zipcode.domain。但目前我认为没有任何方法可以同时满足目标 1 和 3。

Kotlin 开发人员已决定不支持赋值不兼容的类型别名,这将满足您的所有要求,支持等待值 类 在 JVM 上可用,如 [=13= 中所述].