Java has a runtime representation of a class (i.e., Class<X>
) which is just more cumbersome to work with than the python equivalent, in addition java has static fields and therefore has support for python’s “class fields”
I think that the main advantage that a companion object has is in inheritance i.e., it can help with situations like logging - where in java you will have to remember creating a log instance in every class and cannot add specialized methods that uses it in base classes, using the companion object you can do the following:
abstract class Log {
val LOG: Logger
init {
val cls = this::class
if (!cls.isCompanion) throw UnsupportedOperationException("Log object must be a companion object")
//getting the acompanied - I really wish that there was a better way to do so..
val acompanied = Class.forName(cls.java.name.substringBeforeLast('$'))
LOG = LoggerFactory.getLogger(acompanied)
}
inline fun linfo(msg: () -> String) {
if (LOG.isInfoEnabled) LOG.info(msg())
}
inline fun lerror(err: Throwable, msg: () -> String) {
if (LOG.isErrorEnabled) LOG.error(msg(), err)
}
}
class Test {
companion object : Log()
fun someMethod() {
linfo { "starting some method" }
try {
//do something
} catch (err: Throwable) {
lerror(err) {"something bad happened..."}
}
}
}
Other than that - I don’t believe companion objects has any other advantages - but many disadvantages, i.e., slower access time, confusion with X::class
and just X
for newbies, memory overhead, etc.
I also think that statics should be added to kotlin and companion objects should be deprecated and replaced with some sort of class templating mechanism (metaclasses?) that support the above use case in a more pragmatic way