This is a question about language design rather than trying to solve a specific problem.
I noted two oddities about object instances inside companion objects:
.Companion
As shown below, neither constraint applies to functions defined within companion objects. The distinction for apparently for what appear to be sibling declarations is a bit of mental overhead I'd rather not have to deal with.
Is there an example that demonstrates why these constraints were necessary? Presumably for Java interop, but I have yet to think of the case.
class MyClass {
companion object {
@JvmStatic
fun myFunc() {}
//@JvmStatic // Error: This annotation is not applicable to target 'standalone object'
object MyObject {}
}
}
fun testingReferencing() {
MyClass.myFunc()
MyClass.Companion.myFunc() // Awkward and redundant, but works.
//val obj1 = MyClass.MyObject // Error: Unresolved reference: MyObject
val obj2 = MyClass.Companion.MyObject
}
object instances can't be referenced without the
.Companion
This "restriction" is certainly not "necessary", but enabling you to access object declarations this way would probably lead to more complexity in the compiler, to not only implement this, but also handle the edge cases, and various other features that might interact with the change.
And anyway, this is how type names work all along. The fact that you can access properties and methods without Companion
is the exception.
MyClass.MyObject
refers to an object/type called MyObject
, nested in MyClass
. And MyClass.Companion.MyObject
refers to an object/type called MyObject
nested in a type called Companion
, which is itself nested in a type called MyClass
.
This is just the way nested type names (whether they are objects, classes, or interfaces) are qualified.
object instances cannot be annotated
@JvmStatic
JvmStatic
is just unnecessary on type declarations. If you look at the annotation's declaration, it is only available on functions and properties.
An object
(or class
, or enum class
) declaration nested in another type already translates to a static
nested class in Java. e.g.
class Foo {
object Bar
}
translates to something like
public class Foo {
public static class Bar {
public static final INSTANCE = new Bar();
private Bar() {}
}
}
Whether or not it is in a companion object doesn't matter. companion object
, just like class
, translates to a Java class, where the class for the object
is nested.
If you want a non-static JVM class, that is an inner class
in Kotlin.