Reputation: 329
I have something like:
interface Options {
fun load(conf: JsonObject)
}
object BasicOptions : Options { }
object PersonOptions : Options { }
object CarOptions : Options { }
then I would like to get all Objects
that implements Options interface
and call load forEach
.
fun main(args: Array) {
configFuture.whenComplete { config ->
options.forEach { it.load(config) }
}
}
Upvotes: 5
Views: 6451
Reputation: 332
Of course, you can!
Using the Reflections library it's really easy:
First, you need to find all the java classes that implement your interface "Objects". Then you convert the java classes to kotlin classes (KClass).
KClass has the property objectInstance that is null if the class does not have an object instance... otherwise IS the singleton object instance.
So:
val reflections = Reflections(ConfigurationBuilder())
val jList = reflections.getSubTypesOf(Options::class.java)
val kList = jList.map { it.kotlin }
val oList = kList.map { it.objectInstance }.filterNotNull()
;-)
Upvotes: 2
Reputation: 2835
You can always use the Factory
pattern for creating new instances of Options
, that way you can have your own OptionsFactory
and your own caching mechanism.
That OptionsFactory
after instantiating an object keeps it in cache (could be in-memory cache or DB..etc), then anytime you can ask the factory for it's cached instances when needed.
This is fairly better when your Options
objects are created in run-time/upon demand.
Upvotes: 0
Reputation: 11480
This is not supported by the language, this is why there are Dependency Injection, Registry, or Service Lookup solutions.
Another approach is to use custom class loader and add this custom functionality. The simplest way is probably using the Reflections library, to scan and load these classes. E.g.:
val reflections = Reflections("my.project.prefix")
val allClasses = reflections.getSubTypesOf(Options::class.java)
The simplest, and most commonly used solution would be simply maintain your own "registry" e.g. a static object holding the list of all instances. It will require manually adding any new class implementing the interface - but it will be simple, performant, and robust solution.
Upvotes: 3