Aleksey Kozel
Aleksey Kozel

Reputation: 329

Kotlin. Can I get all Objects that implements specific interface

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

Answers (3)

Saxintosh
Saxintosh

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

Ahmed Ashraf
Ahmed Ashraf

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

Lior Bar-On
Lior Bar-On

Reputation: 11480

This is not supported by the language, this is why there are Dependency Injection, Registry, or Service Lookup solutions.

  • If all objects are registered in a Dependency Injection framework, you may be able to iterate all objects registered to the framework and find the instances of your Interface.
    • This is likely to be rather inefficient - so cache the results to avoid the extra overhead.
  • 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

Related Questions