In Kotlin, I want to add a "namespace" to a class that has a set of related functions. Clients of my class will use that namespace to help classify what type of operation they want to do. (I know you're thinking the functions should be in different classes, problem solved. But for other reasons, it's convenient to house all the functions in a single class).
So, I might have a class Uber
that contains fooInsert
fooOpen
fooDispose
along with barInsert
barTerminate
and barHop
. As you can see there's no common interface. Just a bunch of functions that for some reason belong in the same class. Some have an affinity with others (i.e. the fooXXX
functions "belong" together, as do the "barYYY" functions).
What I've come up with is:
class Uber {
inner class FooNamespace {
fun insert(): Unit {}
fun open(): Unit {}
fun dispose(): Unit {}
}
val foo = FooNamespace()
inner class BarNamespace {
fun insert(): Unit {}
fun terminate(): Unit {}
fun hop(): Unit {}
}
val bar = BarNamespace()
}
Users of the class can do something like this:
val uber = Uber()
uber.foo.insert()
uber.bar.hop()
What I'd like is something that combines the inner class ...
and val xxx = XxxNamespace()
into one expression. Something like:
// This doesn't actually compile
val foo = object: inner class {
fun insert(): Unit {}
fun open(): Unit {}
fun dispose(): Unit {}
}
CodePudding user response:
The problem here is that you need a properly defined type if you to want to access these members publicly.
For private properties, the syntax val foo = object { ... }
is sufficient, but for publicly exposed properties these are inferred as Any
and it makes them unusable.
One option is obviously to define an interface for these types, but it's even more boilerplate than what you came up with already, so I am pretty sure this won't suit your needs:
interface FooNamespace {
fun insert()
fun open()
fun dispose()
}
class Uber {
val foo = object : FooNamespace {
override fun insert(): Unit {}
override fun open(): Unit {}
override fun dispose(): Unit {}
}
}
I know you're thinking the functions should be in different classes, problem solved. But for other reasons, it's convenient to house all of the functions in a single class
I'm indeed really thinking that, and would love to hear more about what makes it so convenient to put everything in the same class :) Since the classes are inner classes
, I'm assuming this has to do with accessing private state from Uber
, but that could also be done by wrapping this private state into another class that's passed to foo and bar.
CodePudding user response:
I believe this is not possible, at least for now.
The main technical problem here is that uber.foo.insert()
is really interpreted as chaining uber.foo
and then .insert()
. So for this to work, uber.foo
needs to have an explicitly defined type. It can't be anonymous class/object, because then there is no way to describe what is the type of uber.foo
.
That being said, I've always wondered why Kotlin does not support this syntax:
val foo = object Foo {}
This is consistent with the object declaration where the name of the singleton is at the same time the name of the class. And the compiler even understands this above syntax, because it throws the error: "An object expression cannot bind a name". So Kotlin authors seem to intentionally disallow such use.
I found an issue in the YouTrack, so we can at least upvote it: https://youtrack.jetbrains.com/issue/KT-21329