Imagine you have a following code:
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")
}
}
The whole intent is to provide a static factory method to create a valid value objects (SomeData
, SomeOtherData
) but the validation logic includes some IO operation. So I want to limit the scope of where the create methods may be called to classes that implement SomeClient
.
The problem here is that the compiler can't resolve the companion object methods (SomeData#create
, SomeOtherData#create
) inside of the SomeUseCase#run
, it complains that the receiver is incorrect.
Of course I could do it like that
class SomeUseCase {
fun run() {
val someData = this.createSomeData(...)
val someOtherData = this.createSomeOtherData(...)
}
}
and rename the creation methods accordingly, but I want to keep the names so it would be SomeData.create
, not SomeData.createSomeData
.
Is there a way to achieve this? Does it make sense at all?