Class references


#1

I'm looking for recommendations on how to design something without the use of class references.

Kotlin has javaClass() for compatibility with Java code, but otherwise, there are no class references (unless I’m missing something).
What would the best way to design an API such as the following:

fun <T> setLoader(type:Class<T>, loader: Loader<T>) { loaderMap.put(type, loader) } fun load(file:String, type:Class) { loaderMap.get(type).load(file) }


#2

Reflection and class "literals" are coming, though there is still a lot of work ahead. Meanwhile, you can use recently introduced reified type parameters for inline functions.

 
inline fun LoaderRegistry.setLoaderFor<reified T>(loader: Loader<T>) = setLoader(javaClass<T>(), loader)

and use it like this

registry.setLoaderFor<MyEntity>(EntityLoader())

depending on how rich is your domain space, there could be more DSLs around it, such as:

 
// core traits
trait LoaderRegistry {
    fun setLoader<T>(klass: Class<T>, loader: Loader<T>)
    fun setStrategy<T>(klass: Class<T>, strategy: LoaderStrategy)
}

trait Loader<T>
enum class LoaderStrategy {
  Singleton
  Transient
}

// DSL
class LoaderRegistryDescriptor<T>(val registry: LoaderRegistry, val klass: Class<T>)

inline fun LoaderRegistry.describe<reified T>(body: LoaderRegistryDescriptor<T>.() -> Unit)
  = LoaderRegistryDescriptor(this, javaClass<T>()).body()

fun <T> LoaderRegistryDescriptor<T>.loader(loader: Loader<T>) = registry.setLoader<T>(klass, loader)
fun <T> LoaderRegistryDescriptor<T>.strategy(value: LoaderStrategy) = registry.setStrategy<T>(klass, value)

// domain objects
class MyEntity

class EntityLoader : Loader<MyEntity>

fun fn(registry: LoaderRegistry) {
  registry.describe<MyEntity> {
  loader(EntityLoader())
  strategy(LoaderStrategy.Singleton)
  }
}

With a little effort you can translate loader and strategy DSL functions to properties, if you wish.


#3

Thanks for the quick response. I should have clarified -- It would need to work for both JVM and JS, so using javaClass() won't work.


#4

Is there any way to get the class reference in JS?


#5

Currently Kotlin/JS has no means of reflection. It will be supported a little later later than Kotlin-specific reflection on the JVM.


#6

I had a bit of an "Aha" moment. Classes with class objects can be passed around a bit like a class reference. So in my case, where I want to map a type to an instance, I can use the reference to the class object.

class Foo {
  class object
}

map.put(Foo, true) // Works