2016-02-23 2 views
13

Я пишу две функции расширения для того же класса:У меня есть два метода расширения Котлин для того же класса, но с различными родовыми подписей и компилятор жалуется

class Something<T:Any> { ... } 

Они похожи:

fun Something<Int>.toJson(): String = ... 
fun Something<Double>.toJson(): String = ... 

И приводит к ошибке компилятора:

Kotlin: Platform declaration clash: The following declarations have the same JVM signature

Как создать две функции расширения с различной сигнатурой generics? или это невозможно?

Примечание:этот вопрос намеренно написан и ответил автором (Self-Answered Questions), так что ответы на часто задаваемые вопросы Котлин присутствуют в SO. Он возник в Kotlin slack #general канале.

ответ

17

Kotlin имеет @JvmName annotation специально для этого типа прецедента. В Котлине нет проблемы, потому что она знает разницу между этими методами. Но для байт-кода, совместимого с Java, был бы конфликт для именования, так как генерические подписи были бы идентичны.

Поэтому вам нужно использовать эту аннотацию для управления именем с точки зрения Java и JVM. Ваш код Kotlin не увидит это альтернативное имя и будет использовать имя по вашему желанию.

Изменить код:

@JvmName("somethingIntToJson") fun Something<Int>.toJson(): String = ... 
@JvmName("somethingDoubleToJson") fun Something<Double>.toJson(): String = ... 

От Котлин, используйте обычно:

val someIntyThing = Something<Int>(194) 
val json = someIntyThing.toJson() 
+0

это также работает для параметрических аргументов лямбда – Antek