装箱字符串字段或扩展 Kotlin 中的所有字符串的替代方法?
Alternatives to boxing string field or extending ALL strings in Kotlin?
鉴于无法在 Kotlin 中子class 内置类型,我正在寻找一种方法来向 特定类型的字符串字段 添加特殊方法功能在记录中,而不将这些扩展函数应用于 所有字符串(即使在该记录类型中)。比方说,我在记录中有一些可变字符串字段,我想为其定义特殊用途的行为。
class Customer {
// ...
var zipcode: String
var email: String
// ...
}
- 对于
zipcode
,假设我希望能够调用
thisCustomer.zipcode.plusFour
通过正则表达式获取邮政编码的 +4 (99999-9999)。
- 对于
email
,假设我希望能够调用
thisCustomer.email.domain
有一个正则表达式去得到...@company.com
指定电子邮件的一部分。
我的目标是:
- 避免将
zipcode
装箱成 class Zipcode
的运行时开销
考虑到客户记录集的大小可能是数百万,内部只有一个 var。
- 避免必须赋值的语法
thisCustomer.zipcode.value = "99999-9999"
或 thisCustomer.zipcode = Zipcode("99999-9999")
,如果我最终不得不将字符串装箱。
- 避免添加通用
String.plusFour
和
String.domain
扩展属性,即使只是在客户中
class... 因为邮政编码和电子邮件在技术上可以互相调用
扩展
我一直在考虑这个问题并考虑了以下选项,但每一个都被删除了:
- subclassing 字符串:不可能,因为字符串(和所有内置函数)
已关闭
- 将接口 Zip 应用于 var 声明 (
var zipcode:
String, Zip
):我找不到这样的语法
- 在 getter 本身内添加内部函数:语法似乎不存在
- 使用对象或函数中的函数:想不出办法
为了这个工作,虽然我可能没有足够的想象力
我是否遗漏了一个明显的解决方案?即使不是很明显,利用 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= 中所述].
鉴于无法在 Kotlin 中子class 内置类型,我正在寻找一种方法来向 特定类型的字符串字段 添加特殊方法功能在记录中,而不将这些扩展函数应用于 所有字符串(即使在该记录类型中)。比方说,我在记录中有一些可变字符串字段,我想为其定义特殊用途的行为。
class Customer {
// ...
var zipcode: String
var email: String
// ...
}
- 对于
zipcode
,假设我希望能够调用thisCustomer.zipcode.plusFour
通过正则表达式获取邮政编码的 +4 (99999-9999)。 - 对于
email
,假设我希望能够调用thisCustomer.email.domain
有一个正则表达式去得到...@company.com 指定电子邮件的一部分。
我的目标是:
- 避免将
zipcode
装箱成class Zipcode
的运行时开销 考虑到客户记录集的大小可能是数百万,内部只有一个 var。 - 避免必须赋值的语法
thisCustomer.zipcode.value = "99999-9999"
或thisCustomer.zipcode = Zipcode("99999-9999")
,如果我最终不得不将字符串装箱。 - 避免添加通用
String.plusFour
和String.domain
扩展属性,即使只是在客户中 class... 因为邮政编码和电子邮件在技术上可以互相调用 扩展
我一直在考虑这个问题并考虑了以下选项,但每一个都被删除了:
- subclassing 字符串:不可能,因为字符串(和所有内置函数) 已关闭
- 将接口 Zip 应用于 var 声明 (
var zipcode: String, Zip
):我找不到这样的语法 - 在 getter 本身内添加内部函数:语法似乎不存在
- 使用对象或函数中的函数:想不出办法 为了这个工作,虽然我可能没有足够的想象力
我是否遗漏了一个明显的解决方案?即使不是很明显,利用 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= 中所述].