https://kotlinlang.org logo
#multiplatform
Title
# multiplatform
s

Scott Whitman

12/24/2020, 1:19 PM
I am working on a library using KMP.
KClass.objectInstance
doesn't seem to be available on JS or Native, only JVM. Are there any workarounds or libraries that I can use with expext/actual to accomplish something similar to
T::class.objectInstance
m

Mustafa Ozhan

12/24/2020, 3:30 PM
Hey not sure what is your scenario but you can do it by using
koin
, you will need to make the object singleton example:
Copy code
single { SomeObject() }
then hold this method in
commonMain
Copy code
fun <T> Koin.getDependency(clazz: KClass<*>): T {
    return get(clazz, null) { parametersOf(clazz.simpleName) } as T
}
this will be used for JS,Android and JVM in same module add this method in
iosMain
Copy code
fun <T> Koin.getForIOS(objCClass: ObjCClass): T? = getOriginalKotlinClass(objCClass)?.let {
    getDependency(it)
}
you will call this method from Swift code like this,
Copy code
koin.getForIOS(objCClass: SomeObject.self) as! SomeObject
and from JVM, Android and JS
Copy code
val someObject: SomeObject by lazy {
    koin.getDependency(SomeObject::class)
}
s

Scott Whitman

12/24/2020, 3:48 PM
I'll have to think if I can make that work for me somehow. Here is what I'm trying to do, the 2nd line in my create function
Copy code
// common
public expect inline fun <reified T: Any> KClass<T>.objectInstance(): T?
// JVM
//public actual inline fun <reified T: Any> KClass<T>.objectInstance(): T? = T::class.objectInstance
// JS & Native
//public actual inline fun <reified T: Any> KClass<T>.objectInstance(): T? = TODO()

public sealed class KlassInstance<T : Any>(public open val value: Any) {
    public data class Klass<T : Any, R: T>(override val value: KClass<R>) : KlassInstance<T>(value)
    public data class Instance<T : Any, R: T>(override val value: R) : KlassInstance<T>(value)

    public companion object {

        public inline fun <T : Any, reified R: T> create(instance: R? = null): KlassInstance<T> {
            instance?.let { return Instance(it) }
            R::class.objectInstance()?.let{ return Instance(it) }
            return Klass(R::class)
        }
    }
}
👍 1
r

Robert Jaros

12/24/2020, 8:51 PM
On JS you could probably use:
kClass.js.createInstance()
s

Scott Whitman

12/24/2020, 10:23 PM
Thanks for the tip, I'll try it the next time I'm in front of my computer.
`createInstance()`is not available on my
KClass.js
? Is there a dependency I can add to get it?
r

Robert Jaros

12/25/2020, 2:35 AM
I'm sorry, I haven't noticed the
createInstance
function is in fact my own function 🙂 But feel free to use it:
Copy code
fun <T> Any?.createInstance(vararg args: dynamic): T {
    val jsClassConstructor = this
    val argsArray = (listOf<dynamic>(null) + args).toTypedArray()
    return js("new (Function.prototype.bind.apply(jsClassConstructor, argsArray))").unsafeCast<T>()
}
you can make it
JsClass<T>
extension for your need