Доступ к значению параметра функции по умолчанию в Kotlin

Можно ли получить доступ к значению параметра функции по умолчанию из расширения функции или где-либо еще?

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

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

person ersin-ertan    schedule 20.08.2017    source источник
comment
Нет, не может. Поскольку значение параметра по умолчанию может быть произвольным выражением с возможными побочными эффектами, было бы не совсем ясно и интуитивно использовать его где-либо явно: какова должна быть семантика, должен ли он оцениваться при каждом использовании или нет?   -  person hotkey    schedule 20.08.2017
comment
Как насчет того, чтобы просто сохранить минимальное и максимальное значения как константы? Это также улучшит видимость доступа.   -  person creativecreatorormaybenot    schedule 20.08.2017


Ответы (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()
person guenhter    schedule 21.08.2017