Hi Kotlin Community.
I have stumbled upon this syntax, defining a function inside a function, a few days ago and I have a few questions on it.
like so
fun setupUI(score: Int) {
fun getProperColor() = if (score > 0) Color.GREEN else Color.RED
ui.text.textColor = getProperColor()
ui.text.onClick { ui.someOtherText.textColor = getProperColor() }
}
- What is the equivalent to this in Java.
- I am trying to increase extensibility here ( if the business for color changes, i change the function and it would work for all texts) . Does it impact performace or memory in any way ?
Thanks in advance
Java equivalent:
void setupUI(int score) {
Supplier<Color> getProperColor = () -> score > 0 ? Color.GREEN : Color.RED;
ui.text.textColor = getProperColor.get()
ui.text.onClick(() -> ui.someOtherText.textColor = getProperColor.get());
}
So it basically generates an instance of an interface ?
From what I can tell, it generates a class implementing the proper interface from kotlin/jvm/functions. So in this case, it would be Function0.
If that is true, therefore copy pasting the code can be faster for the system
Nope! Wrong!
fun function1() {
fun function2() {
}
function2()
}
compiles to
public final class TestKt {
public final static function1()V
L0
LINENUMBER 4 L0
GETSTATIC TestKt$function1$1.INSTANCE : LTestKt$function1$1;
ASTORE 0
L1
LINENUMBER 7 L1
ALOAD 0
CHECKCAST TestKt$function1$1
INVOKEVIRTUAL TestKt$function1$1.invoke ()V
L2
LINENUMBER 8 L2
RETURN
L3
LOCALVARIABLE function2$ LTestKt$function1$1; L1 L3 0
MAXSTACK = 1
MAXLOCALS = 1
final static INNERCLASS TestKt$function1$1 null null
}
final class TestKt$function1$1 extends kotlin/jvm/internal/Lambda implements kotlin/jvm/functions/Function0 {
public synthetic bridge invoke()Ljava/lang/Object;
ALOAD 0
INVOKEVIRTUAL TestKt$function1$1.invoke ()V
GETSTATIC kotlin/Unit.INSTANCE : Lkotlin/Unit;
ARETURN
MAXSTACK = 1
MAXLOCALS = 1
public final invoke()V
L0
LINENUMBER 6 L0
RETURN
L1
LOCALVARIABLE this LTestKt$function1$1; L0 L1 0
MAXSTACK = 0
MAXLOCALS = 1
<init>()V
ALOAD 0
ICONST_0
INVOKESPECIAL kotlin/jvm/internal/Lambda.<init> (I)V
RETURN
MAXSTACK = 2
MAXLOCALS = 1
public final static LTestKt$function1$1; INSTANCE
static <clinit>()V
NEW TestKt$function1$1
DUP
INVOKESPECIAL TestKt$function1$1.<init> ()V
PUTSTATIC TestKt$function1$1.INSTANCE : LTestKt$function1$1;
RETURN
MAXSTACK = 2
MAXLOCALS = 0
OUTERCLASS TestKt function1 ()V
final static INNERCLASS TestKt$function1$1 null null
}
What does this mean? The Kotlin compiler generates a singleton class which implements the Function interface. The compiler DOES NOT generate a new instance of the function every time the parent function is called.
Exactly - But it’s a singleton class with only one instance.
@nyxcode
Like many other lambdas, instances can’t be singletons unless no variables are captured from the scope (scope variables include this).
If no variables are being captured, instance can be a singleton, and the Kotlin compiler can make that optimization.