Как перегружать конструкторы в котлин отличается в лямбда-обратном типе

У меня есть два конструктора, которые отличаются только в своем возвратном типе лямбда. Есть ли способ перегрузить их? Я пытался использовать аннотацию JvmOverloads , но это не сработало.

constructor(db : Database, handler: ( transaction: Transaction) -> Unit) : this(db, Handler<Transaction>( {handler.invoke(it)})) @JvmOverloads constructor(db : Database, handler: ( transaction: Transaction) -> Any) : this(db, Handler<Transaction>( {handler.invoke(it)})) 

Вы не можете определить конструкторы с сигнатурами, которые отличаются только общими параметрами (в вашем случае это общие параметры для Function1<in P1, out R> ), потому что подписи будут сталкиваться после стирания дженериков.

Однако в вашем случае Unit является подтипом Any , а так как Function<in P1, out R> является ковариантным на R , вы можете передать функцию, которая возвращает Unit ко второму конструктору, поэтому просто удалите первый.

Упрощенный пример:

 class C(val action: (Int) -> Any) fun main(args: Array<String>) { val f: (Int) -> Unit = { println(it) } C(f) } 

Для более сложных случаев @JvmName к заводским функциям : в отличие от конструкторов, вы можете аннотировать их с @JvmName чтобы избежать столкновения сигнатур:

 @JvmName("createCUnit") fun createC(f: (Int) -> Unit) = C(f) fun createC(f: (Int) -> Any) = C(f) 

При ориентации на JVM-сервер все классы Kotlin скомпилированы в байт-код JVM. Проблема с байт-кодом java – стирание типа . Это означает, что вся информация о дженериках удалена (это проблема Java не Kotlin's).

Объявление функционального типа (transaction: Transaction) -> Unit является эквивалентной для использования этого типа: Function1<Transaction, Unit> . Однако для байт-кода JVM оба Function1<Transaction, Unit> и Function1<Transaction, Any> одинаковы.

Это означает, что оба ваших конструктора имеют одну и ту же подпись в мире JVM.

Вы можете «имитировать» конструкторы с помощью companion object

 class MyClass { constructor(db: Database, h: Handler<Transaction>) companion object { operator fun invoke(db: Database, handler: (transaction: Transaction) -> Unit) = MyClass(db, Handler<Transaction>({ handler.invoke(it) })) @JvmName("alternative_constructor") operator fun invoke(db: Database, handler: (transaction: Transaction) -> Any) = MyClass(db, Handler<Transaction>({ handler.invoke(it) })) } } 

И использование выглядит так:

 fun main(args: Array<String>) { val db = Database() MyClass(db, Handler { }) //real constructor MyClass(db){ } //version from companion object } 
Intereting Posts
Использование ресурса в kotlin func – не работает с жирным банком (одна банка) Как подсчитать методы в библиотеке Котлин Триггер с использованием Teamcity Kotlin DSL kotlin if (bar == null) vs. bar?: run Android Room, добавление классов библиотеки данных в базу данных Требуется ли знание Groovy для понимания Gradle? Попытка загрузить файл в основное действие onCreate Сортировка объектов по алфавиту Вызовите супер в конструкторе и назначьте поле в Котлине? Есть ли лучший способ получить доступ к свойствам с возможностью NULL? Параметры аргумента функции kotlin по умолчанию из java Recyclerview: прослушивание событий с добавлением кликов Ошибка в валидаторе привязки данных от Ilhasoft + Kotlin Как сортировать на основе / сравнивать несколько значений в Котлин? В Котлине, почему Джексон в некоторых случаях отказывается от несанкционированного не аннотированного объекта, а не в других