Kotlin - 有没有一种方法可以定义函数的显式范围,并在伴随对象中定义接收者?
Kotlin - Is there a way of defining an explicit scope of a function with receiver defined in companion object?
假设您有以下代码:
interface SomeClient {
fun isValid(value: String): Boolean
}
class SomeData private constructor(
val value: String
) {
companion object {
fun SomeClient.create(value: String): SomeData? =
if (isValid(value)) {
SomeData(value)
} else {
null
}
}
}
class SomeOtherData private constructor(
val otherValue: String
) {
companion object {
fun SomeClient.create(value: String): SomeOtherData? =
if (isValid(value)) {
SomeOtherData(value)
} else {
null
}
}
}
class SomeUseCase(
someClient: SomeClient
) : SomeClient by someClient {
fun run() {
val someData = SomeData.create("hello")
val someOtherData = SomeOtherData.create("wassup")
}
}
整个意图是提供一个静态工厂方法来创建有效值对象(SomeData
、SomeOtherData
),但验证逻辑包括一些 IO 操作。所以我想将创建方法的调用范围限制为实现 SomeClient
.
的 类
这里的问题是编译器无法解析SomeUseCase#run
内部的伴生对象方法(SomeData#create
、SomeOtherData#create
),它会抱怨接收者不正确。
我当然可以那样做
class SomeUseCase {
fun run() {
val someData = this.createSomeData(...)
val someOtherData = this.createSomeOtherData(...)
}
}
并相应地重命名创建方法,但我想保留这些名称,所以它是 SomeData.create
,而不是 SomeData.createSomeData
。
有办法实现吗?这有什么意义吗?
当您在 SomeData
伴随对象中编写 fun SomeClient.create(value: String)
时,您并不是在为伴随对象定义 create
方法,而是为 SomeClient
在伴随对象的范围。
如果你重写它使它成为伴随对象的方法,你会看到 isValid
() 调用没有接收者,所以它需要作为参数传递到那里:
class SomeData private constructor(val value: String) {
companion object {
fun create(value: String, validator: SomeClient): SomeData? =
if (validator.isValid(value)) SomeData(value) else null
}
}
之后可以在SomeClient
的范围内这样调用:
val someData = SomeData.create("hello", this)
每次创建调用都要重复this
有点麻烦,所以你可以在SomeClient
接口的范围内为SomeData
伴生对象定义一个扩展函数:
interface SomeClient {
fun isValid(value: String): Boolean
fun SomeData.Companion.create(value: String) = create(value, this@SomeClient)
}
之后可以在 SomeClient
的范围内以所需的方式调用它:
val someData = SomeData.create("hello")
假设您有以下代码:
interface SomeClient {
fun isValid(value: String): Boolean
}
class SomeData private constructor(
val value: String
) {
companion object {
fun SomeClient.create(value: String): SomeData? =
if (isValid(value)) {
SomeData(value)
} else {
null
}
}
}
class SomeOtherData private constructor(
val otherValue: String
) {
companion object {
fun SomeClient.create(value: String): SomeOtherData? =
if (isValid(value)) {
SomeOtherData(value)
} else {
null
}
}
}
class SomeUseCase(
someClient: SomeClient
) : SomeClient by someClient {
fun run() {
val someData = SomeData.create("hello")
val someOtherData = SomeOtherData.create("wassup")
}
}
整个意图是提供一个静态工厂方法来创建有效值对象(SomeData
、SomeOtherData
),但验证逻辑包括一些 IO 操作。所以我想将创建方法的调用范围限制为实现 SomeClient
.
这里的问题是编译器无法解析SomeUseCase#run
内部的伴生对象方法(SomeData#create
、SomeOtherData#create
),它会抱怨接收者不正确。
我当然可以那样做
class SomeUseCase {
fun run() {
val someData = this.createSomeData(...)
val someOtherData = this.createSomeOtherData(...)
}
}
并相应地重命名创建方法,但我想保留这些名称,所以它是 SomeData.create
,而不是 SomeData.createSomeData
。
有办法实现吗?这有什么意义吗?
当您在 SomeData
伴随对象中编写 fun SomeClient.create(value: String)
时,您并不是在为伴随对象定义 create
方法,而是为 SomeClient
在伴随对象的范围。
如果你重写它使它成为伴随对象的方法,你会看到 isValid
() 调用没有接收者,所以它需要作为参数传递到那里:
class SomeData private constructor(val value: String) {
companion object {
fun create(value: String, validator: SomeClient): SomeData? =
if (validator.isValid(value)) SomeData(value) else null
}
}
之后可以在SomeClient
的范围内这样调用:
val someData = SomeData.create("hello", this)
每次创建调用都要重复this
有点麻烦,所以你可以在SomeClient
接口的范围内为SomeData
伴生对象定义一个扩展函数:
interface SomeClient {
fun isValid(value: String): Boolean
fun SomeData.Companion.create(value: String) = create(value, this@SomeClient)
}
之后可以在 SomeClient
的范围内以所需的方式调用它:
val someData = SomeData.create("hello")