Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does erasure work in Kotlin?

Tags:

kotlin

In Kotlin, the following code compiles:

class Foo {     fun bar(foo: List<String>): String {         return ""     }      fun bar(foo: List<Int>): Int {         return 2;     } } 

This code, however, does not:

class Foo {     fun bar(foo: List<String>): String {         return ""     }      fun bar(foo: List<Int>): String {         return "2";     } } 

Compiling this will cause the following error:

Error:(8, 5) Kotlin: Platform declaration clash: The following declarations have the same JVM signature (foo(Ljava/util/List;)Ljava/lang/String;):     fun foo(layout: List<Int>): String     fun foo(layout: List<String>): String 

In Java, neither example will compile:

class Foo {     String bar(List<Integer> foo) {         return "";     }      Integer bar(List<String> foo) {         return 2;     } }  class Foo {     String bar(List<Integer> foo) {         return "";     }      String bar(List<String> foo) {         return "2";     } } 

Unsurprisingly, both of the prior snippets generate the familiar compiler error:

Error:(13, 12) java: name clash: bar(java.util.List<java.lang.String>) and bar(java.util.List<java.lang.Integer>) have the same erasure 

What surprises me is that the first Kotlin example works at all, and second, if it works, why does the second Kotlin example fail? Does Kotlin consider a method's return type as part of its signature? Furthermore, why do method signatures in Kotlin respect the full parameter type, in contrast with Java?

like image 532
breandan Avatar asked Mar 21 '17 01:03

breandan


People also ask

What is type erasure in Kotlin?

Type Erasure. As with Java, Kotlin's generics are erased at runtime. That is, an instance of a generic class doesn't preserve its type parameters at runtime. For example, if we create a Set<String> and put a few strings into it, at runtime we're only able to see it as a Set.

Does Kotlin use type erasure?

Type erasure The type safety checks that Kotlin performs for generic declaration usages are done at compile time. At runtime, the instances of generic types do not hold any information about their actual type arguments. The type information is said to be erased.

How does type erasure work?

Type erasure is a process in which compiler replaces a generic parameter with actual class or bridge method. In type erasure, compiler ensures that no extra classes are created and there is no runtime overhead.

What is out T in Kotlin?

"Out" keyword is extensively used in Kotlin generics. Its signature looks like this − List<out T> When a type parameter T of a class C is declared out, then C can safely be a super type of C<Derived>. That means, a Number type List can contain double, integer type list.


1 Answers

Actually Kotlin knows the difference between the two methods in your example, but jvm will not. That's why it's a "platform" clash.

You can make your second example compile by using the @JvmName annotation:

class Foo {   @JvmName("barString") fun bar(foo: List<String>): String {     return ""   }    @JvmName("barInt") fun bar(foo: List<Int>): String {     return "2";   } } 

This annotation exists for this very reason. You can read more in the interop documentation.

like image 81
Strelok Avatar answered Sep 23 '22 17:09

Strelok