Skip to content

Instantly share code, notes, and snippets.

@LouisCAD
Last active January 21, 2024 07:45
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save LouisCAD/8ec67b6473e98d28f4609ac31869c80f to your computer and use it in GitHub Desktop.
Save LouisCAD/8ec67b6473e98d28f4609ac31869c80f to your computer and use it in GitHub Desktop.
Demonstration of the powers of companion objects when it comes to discoverability. Great alternative to java-style "factories".
package i_love_companion_objects
suspend fun main() {
// Discoverability is easy with the companion object
// (although autocomplete could use some performance improvements...)
doStuff(SomeInterface.createWithDefaults())
val someInstance: SomeInterface = SomeInterface.create(
parameterOne = 0,
parameterTwo = 1
)
doStuff(someInstance)
doStuff(SomeInterface.appInstance)
}
// This is a random function that would need an instance of SomeInterface.
private suspend fun doStuff(someInterface: SomeInterface) {
someInterface.someFunction()
}
// Extension property on the companion object, easy to discover.
val SomeInterface.Companion.appInstance: SomeInterface get() = someInterfaceAppInstance
private val someInterfaceAppInstance = SomeInterface.create(0, 0)
package i_love_companion_objects
interface SomeInterface {
companion object; // Semicolon needed to avoid next word ("suspend" in this case)
// being picked up as the companion object name.
// BTW, here, we keep the default one, which is "Companion".
// This is a random function, we don't really care about it, the focus is companion objects.
suspend fun someFunction()
}
package i_love_companion_objects
// Extension function on the companion object, easy to discover. Can use any name.
fun SomeInterface.Companion.create(
parameterOne: Any,
parameterTwo: Any
): SomeInterface {
return SomeInterfaceImpl(
parameterOne = parameterOne,
parameterTwo = parameterTwo
)
}
private class SomeInterfaceImpl(
private val parameterOne: Any,
private val parameterTwo: Any
) : SomeInterface {
override suspend fun someFunction() {
println("FYI: someFunction called in $javaClass with some parameters :)")
}
}
package i_love_companion_objects
import kotlinx.coroutines.*
// Extension function on the companion object, easy to discover. Can be suspending.
suspend fun SomeInterface.Companion.createWithDefaults(): SomeInterface {
return SomeInterfaceOtherImpl(
someParameter = pretendToDoSomeWorkAndReturnIt()
)
}
// Looks like a constructor, but suspends. Could take any parameters, can have overloads.
suspend operator fun SomeInterface.Companion.invoke(): SomeInterface {
return createWithDefaults()
}
private suspend fun pretendToDoSomeWorkAndReturnIt(): Any {
return delay(timeMillis = 10)
}
// Implementation is hidden, no need to guess its name.
private class SomeInterfaceOtherImpl(
private val someParameter: Any
) : SomeInterface {
override suspend fun someFunction() {
println("FYI: someFunction called in $javaClass having someParameter set to $someParameter")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment