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.