Accessing a function's default parameter value in Kotlin

前端 未结 1 545
死守一世寂寞
死守一世寂寞 2021-01-19 17:30

Can a function\'s default parameter value be accessed from a function extension, or anywhere else?

fun DieRoll.cheatRoll():Int = roll(min = max -1)

fun roll         


        
相关标签:
1条回答
  • 2021-01-19 17:58

    No, this is not possible. The default values are not accessible. They are just contained in a bridge-method in the bytecode:

    fun test(a: Int = 123) {
    }
    
    fun test2() {
        test()
        test(100)
    }
    

    Results in the bytecode:

    public final test(int arg0) { //(I)V
         <localVar:index=0 , name=this , desc=Lorg/guenhter/springboot/kt/Fun;, sig=null, start=L1, end=L2>
         <localVar:index=1 , name=a , desc=I, sig=null, start=L1, end=L2>
    
         L1 {
             return
         }
         L2 {
         }
     }
    
     public static bridge test$default(org.guenhter.springboot.kt.Fun arg0, int arg1, int arg2, java.lang.Object arg3) { //(Lorg/guenhter/springboot/kt/Fun;IILjava/lang/Object;)V
             iload2 // reference to arg2
             iconst_1
             iand
             ifeq L1
         L2 {
             bipush 123  // <-- THIS IS YOUR DEFAULT VALUE
             istore1 // reference to arg1
         }
         L1 {
             aload0 // reference to arg0
             iload1 // reference to arg1
             invokevirtual org/guenhter/springboot/kt/Fun test((I)V);
             return
         }
     }
    
     public final test2() { //()V
         <localVar:index=0 , name=this , desc=Lorg/guenhter/springboot/kt/Fun;, sig=null, start=L1, end=L2>
    
         L1 {
             aload0 // reference to self
             iconst_0
             iconst_1
             aconst_null
             invokestatic org/guenhter/springboot/kt/Fun test$default((Lorg/guenhter/springboot/kt/Fun;IILjava/lang/Object;)V);
         }
         L3 {
             aload0 // reference to self
             bipush 100
             invokevirtual org/guenhter/springboot/kt/Fun test((I)V);
         }
         L4 {
             return
         }
         L2 {
         }
     }
    

    which in Java syntax would look like

    final public class AKt {
        final public static void test(int i) {
        }
    
        public static void test$default(int i, int i0, Object a) {
            if ((i0 & 1) != 0) {
                i = 123;
            }
            AKt.test(i);
        }
    
        final public static void test2() {
            AKt.test$default(0, 1, (Object)null);
            AKt.test(100);
        }
    }
    

    So the best alternative for you would be to extract the default value into a constant:

    private val DEFAULT_MIN = 1
    private val DEFAULT_MAX = 1
    
    fun DieRoll.cheatRoll():Int = roll(min = DEFAULT_MAX-1)
    
    fun roll(min: Int = DEFAULT_MIN, max: Int = DEFAULT_MAX): Int = (min..max).rand()
    
    0 讨论(0)
提交回复
热议问题