kotlin function default arguments from java

前端 未结 2 1694
面向向阳花
面向向阳花 2021-02-11 14:01

given following Kotlin class:

class Foo {
   public fun bar(i: Int = 0): Int = 2 * i
}

How should I call \'bar\' function without any parameter

2条回答
  •  -上瘾入骨i
    2021-02-11 14:55

    I'll post the real answer shortly, but if anyone is wanting to do this from reflection, here is how the code would look. Much more complicated, but educational about how to use Kotlin reflection for KCallable.

    Here is the class to call:

     class Foo {
        public fun bar(name: String = "World"): String = "Hello $name!"
    }
    

    Then we need a utility class in Kotin that can receive an instance of a class, a method from java reflection, and the parameters by name. This only works with non-primitives:

    class KReflectHelper {
        companion object {
            @Suppress("UNCHECKED_CAST")
            @JvmStatic fun  callKotlinMethodWithNamedParms(instance: Any, method: Method, parmMap: Map): T {
                val callable: KFunction = method.kotlinFunction as? KFunction ?: throw IllegalStateException("Method is not a Kotlin method")
                val unusedParms = HashSet(parmMap.keys)
                val callableParms = hashMapOf()
                callable.parameters.map { parm ->
                    if (parm.kind == KParameter.Kind.INSTANCE) {
                        callableParms.put(parm, instance)
                    } else if (parm.kind == KParameter.Kind.VALUE && parmMap.contains(parm.name)) {
                        unusedParms.remove(parm.name)
                        callableParms.put(parm, parmMap.get(parm.name))
                    } else if (parm.kind == KParameter.Kind.VALUE) {
                        if (parm.isOptional) {
                            // default value will be used!
                        } else {
                           throw IllegalStateException("Missing required parameter ${parm.name}")
                        }
                    } else {
                        throw IllegalStateException("Cannot call methods that are not direct instance methods")
                    }
                }
                if (unusedParms.isNotEmpty()) {
                    throw IllegalStateException("Unrecognized parameters passed to function: $unusedParms")
                }
                return method.kotlinFunction?.callBy(callableParms) as T
            }
        }
    }
    

    Now that static method can be called from Java, but it isn't so much fun. A code generator would really be required. Calling it from Kotlin is much easier and some frameworks (such as Klutter and Kovert) already use something along these lines.

        Foo foo = new Foo();
        System.out.println(foo.bar("Frank"));
    
        Method barMethod = Foo.class.getMethod("bar", String.class);
    
        Map parms = new HashMap();
    
        parms.put("name", "David");
        System.out.println(KReflectHelper.callKotlinMethodWithNamedParms(foo, barMethod, parms));
    
        // now call using the default
        parms.clear();
        System.out.println(KReflectHelper.callKotlinMethodWithNamedParms(foo, barMethod, parms));
    

    Ouput:

    Hello Frank!

    Hello David!

    Hello World!

提交回复
热议问题