2017-09-11 6 views
2
class X { 
    fun someFunc(x: Int, y: String, z: Double) { 
     println("x = [$x], y = [$y], z = [$z]") 
    } 
} 

fun main(args: Array<String>) { 
    val func = X::someFunc 
    val instance = X() 

    func.call(instance, 1, "Hi", 123.45) 
} 

上記のコードでは、インスタンスを組み込んだ関数に変換するにはどうすればいいですか?呼び出すときには、instanceを使わないでパラメータを渡すだけですか? (私はちょうどX()::someFuncを使用できましたが、それはこの質問のポイントではありません)インスタンス関数を持たないKFunctionをKFunctionに変換するにはどうすればよいですか?

答えて

1

そのロジックをラップするデリゲートを実装することができます。実装例:

class KCallableWithInstance<out T>(private val func: KCallable<T>, private val instance: Any) : KCallable<T> by func { 
    private val instanceParam = func.instanceParameter ?: 
      func.extensionReceiverParameter ?: 
      throw IllegalArgumentException("Given function must not have a instance already bound") 

    init { 
     val instanceParamType = instanceParam.type.jvmErasure 
     if (!instance::class.isSubclassOf(instanceParamType)) 
      throw IllegalArgumentException(
        "Provided instance (${instance::class.qualifiedName}) isn't an subclass of " + 
          "instance param's value's class (${instanceParamType::class.qualifiedName})") 
    } 

    override fun call(vararg args: Any?): T 
      = func.call(instance, *args) 


    override fun callBy(args: Map<KParameter, Any?>): T 
      = func.callBy(args + (instanceParam to instance)) 

    override val parameters = func.parameters.filter { it != instanceParam } 

} 

fun <T> KCallable<T>.withInstance(instance: Any): KCallable<T> 
     = KCallableWithInstance(this, instance) 

そして、このようにそれを使用します(例を問題のコードに基づく):func.withInstance(instance).call(1, "Hi", 123.45)

関連する問題