【问题标题】:Accessing a function's default parameter value in Kotlin在 Kotlin 中访问函数的默认参数值
【发布时间】:2017-08-20 20:16:23
【问题描述】:

可以从函数扩展或其他任何地方访问函数的默认参数值吗?

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

fun roll(min: Int = 1, max: Int = 6): Int = (min..max).rand()

【问题讨论】:

  • 不,它不能。由于参数的默认值可以是具有可能副作用的任意表达式,因此在任何地方显式使用它都不是很清晰和直观:语义应该是什么,是否应该在每次使用时对其进行评估?
  • 将最小值和最大值存储为常量怎么样?这也会使访问可见性更好。

标签: kotlin default-value default-parameters


【解决方案1】:

不,这是不可能的。无法访问默认值。它们只是包含在字节码中的 bridge-method 中:

fun test(a: Int = 123) {
}

fun test2() {
    test()
    test(100)
}

字节码中的结果:

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 {
     }
 }

Java 语法中的样子

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);
    }
}

所以对你来说最好的选择是将默认值提取到一个常量中:

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()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-24
    • 1970-01-01
    • 2020-07-21
    • 2011-02-20
    • 2011-04-09
    • 1970-01-01
    • 2021-07-27
    相关资源
    最近更新 更多