假设您有以下代码:
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操作。因此,我想将可调用create方法的范围限制为实现SomeClient
的类。
这里的问题是,编译器无法解析SomeData#create
内的伴随对象方法(SomeOtherData#create
,SomeUseCase#run
),它抱怨接收者不正确。
我当然可以那样做
class SomeUseCase {
fun run() {
val someData = this.createSomeData(...)
val someOtherData = this.createSomeOtherData(...)
}
}
并相应地重命名创建方法,但我想保留名称,使其为SomeData.create
,而不是SomeData.createSomeData
。
有没有办法做到这一点?真的有道理吗?
答案 0 :(得分:2)
在fun SomeClient.create(value: String)
随播对象中编写SomeData
时,您不是在为随播对象定义create
方法,而是在SomeClient
的范围内为isValid
定义extension function随播对象。
如果重写它使其成为伴侣对象的方法,您将看到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
对于每个创建调用重复SomeData
有点麻烦,因此您可以在SomeClient
接口范围内为interface SomeClient {
fun isValid(value: String): Boolean
fun SomeData.Companion.create(value: String) = create(value, this@SomeClient)
}
伴随对象定义扩展功能:
SomeClient
此后,可以按所需方式在val someData = SomeData.create("hello")
范围内调用它:
locale