kevin.cianfarini
08/24/2017, 3:20 AMgildor
08/24/2017, 3:41 AMfun <T> foo() {
println(T::class) //Will not compile
}
But Kotlin supports also reified generics (but only for inline functions), it means that compiler will compile this code in different way and allow you access to real generic type class:
inline fun <reified T> foo() {
println(T::class) //Works fine
}
arekolek
08/24/2017, 8:32 AMinline fun <reified T> View.findParentOfType(): T? {
var p = parent
while (p != null && p !is T) p = p.parent
return p as T?
}
which lets me call for example:
email.findParentOfType<TextInputLayout>()?.error ?: email.error
The function gets decompiled to:
private static final Object findParentOfType(@NotNull View $receiver) {
ViewParent p;
for(p = $receiver.getParent(); p != null; p = p.getParent()) {
Intrinsics.reifiedOperationMarker(3, "T");
if(p instanceof Object) {
break;
}
}
Intrinsics.reifiedOperationMarker(1, "T?");
return (Object)p;
}
Which leaves the question of how it works open to me, honestly. What’s up with the if(p instanceof Object) break;
? 😄gildor
08/24/2017, 8:38 AMkevin.cianfarini
08/24/2017, 4:01 PMarekolek
08/25/2017, 9:56 AMinline fun <reified T> View.parentIsInstance() = parent is T
shows this bytecode:
// access flags 0x1A
// signature <T:Ljava/lang/Object;>(Landroid/view/View;)Z
// declaration: boolean parentIsInstance<T>(android.view.View)
private final static parentIsInstance(Landroid/view/View;)Z
@Lorg/jetbrains/annotations/NotNull;() // invisible, parameter 0
L0
LINENUMBER 137 L0
ALOAD 0
INVOKEVIRTUAL android/view/View.getParent ()Landroid/view/ViewParent;
ICONST_3
LDC "T"
INVOKESTATIC kotlin/jvm/internal/Intrinsics.reifiedOperationMarker (ILjava/lang/String;)V
INSTANCEOF java/lang/Object
IRETURN
L1
LOCALVARIABLE $receiver Landroid/view/View; L0 L1 0
LOCALVARIABLE $i$f$parentIsInstance I L0 L1 1
MAXSTACK = 3
MAXLOCALS = 2
Decompiled to:
private static final boolean parentIsInstance(@NotNull View $receiver) {
ViewParent var10000 = $receiver.getParent();
Intrinsics.reifiedOperationMarker(3, "T");
return var10000 instanceof Object;
}
reifiedOperationMarker
always throws an exception if ever calledinline fun <reified T> View.parentIsInstance() = parent is T
fun testReified(x: View) = x.parentIsInstance<LinearLayout>()
gets decompiled to:
private static final boolean parentIsInstance(@NotNull View $receiver) {
ViewParent var10000 = $receiver.getParent();
Intrinsics.reifiedOperationMarker(3, "T");
return var10000 instanceof Object;
}
public static final boolean testReified(@NotNull View x) {
Intrinsics.checkParameterIsNotNull(x, "x");
return x.getParent() instanceof LinearLayout;
}
which now totally makes sense.