替代拳击字符串字段或扩展在Kotlin的所有字符串?

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

class Customer { // ... var zipcode: String var email: String // ... } 
  • 对于zipcode ,假设我希望能够通过正则表达式来调用thisCustomer.zipcode.plusFour来获取邮政编码(99999-9999)的+4。
  • 对于email ,假设我希望能够调用thisCustomer.email.domain使正则表达式得到指定电子邮件的@@ company.com部分。

我的目标是:

  1. 考虑到客户记录集的大小可能可能是数百万,所以避免将拳击zipcode的运行时间开销放入只有一个内部class Zipcode Zipcode中。
  2. 避免必须分配thisCustomer.zipcode.value = "99999-9999"thisCustomer.zipcode = Zipcode("99999-9999")的语法,如果我最终不得不装箱的话。
  3. 避免添加一般的String.plusFourString.domain扩展属性,即使在Customer类中也是如此……因为邮政编码和电子邮件在技术上可以互相呼叫对方的扩展

我一直在考虑这个问题,并考虑了下面的选项,

  • 子类化字符串: 由于字符串(和所有内置函数)被关闭,所以不可能
  • 将一个接口Zip应用到var声明( var zipcode: String, Zip ): 没有这样的语法,我可以找到
  • 在getter本身中添加内部函数: 语法似乎不存在
  • 使用对象或功能内功能: 想不到一个方法,这个工作,虽然我可能不足够的想象力

我错过了一个明显的解决办法吗? 即使不是很明显,用Kotlin的所有语法魔法,有没有办法让它发生? 也许有一种方法可以完成上述某些/所有的目标而不使用任何这些方法?

你可以使用类型别名来明确意图:

 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上等待值类的使用,正如https://github.com/Kotlin/KEEP/issues / 4 。

你可以使用委托创建一个装饰器类:

 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)