Интерфейс фабрики Kotlin с дженериками

У меня есть заводский интерфейс в моем коде Kotlin, например (используя Guava TypeToken ):

 interface ResultMapperFactory { fun <T> get(type: TypeToken<T>, context: MapperLookupContext): ResultMapper<T>? } 

Все идет нормально. Это очень легко использовать при вызове, однако для реализации почти всегда требуется небезопасное исполнение:

 object StringFactory : ResultMapperFactory { override fun <T> get(type: TypeToken<T>, context: MapperLookupContext): ResultMapper<T>? { return if (type.rawType == String::class.java) MyStringMapper as ResultMapper<T> else null } } 

Это уродливо, но я победил его с помощью трюка. Во-первых, небольшая функция полезности для создания экземпляров TypeToken :

 inline fun <reified T> typeToken(): TypeToken<T> = object : TypeToken<T>() {} 

Теперь я добавил объект-компаньон к моему заводскому интерфейсу:

 companion object { inline operator fun <reified R> invoke(crossinline body: (TypeToken<R>, MapperLookupContext) -> ResultMapper<R>?): ResultMapperFactory { val t = typeToken<R>().type return object : ResultMapperFactory { override fun <T> get(type: TypeToken<T>, context: MapperLookupContext): ResultMapper<T>? { return if (type.isSubtypeOf(t)) body(type as TypeToken<R>, context) as ResultMapper<T>? else null } } } } 

Это позволяет мне иметь непроверенный (но безопасный) перевод в одном месте, и я могу написать код следующим образом:

 val stringMapper: ResultMapper<String> = TODO() val stringMapperFactory = ResultMapperFactory<String> { type, context -> stringMapper } 

Однако этот подход также разваливается, как только я хочу реализовать фабрику, которая принимает TypeToken<List<T>> и возвращает ResultMapper<List<T>> , потому что мне негде поставить этот параметр T

Я очень хочу услышать ваши предложения.

Я нашел решение самостоятельно, используя invoke оператора, которую я опубликовал в своем первоначальном вопросе, могу написать следующее:

 private class ListResultMapper<out E>(private val elementMapper: ResultMapper<E>) : ResultMapper<List<E>> { /* ... */ } val listMapperFactory = ResultMapperFactory<List<*>> { type, context -> context.resultMapperFactory.get(type.elementType(), context)?.let { ListResultMapper(it) } } 
Intereting Posts
Невозможно заменить SAM-конструктор лямбдой, когда первый аргумент – это класс с одним методом Разница между Lock.withLock и синхронизация в Kotlin Неопределенность разрешения перегрузки при вызове Http.get Инструменты статического анализа для языка программирования Kotlin? проблемы с макетами и ошибки в приложении android, разработанные с использованием kotlin IllegalArgumentException: savedInstanceState Указано как Non-Null Null Как исправить мой код, чтобы удалить предупреждение о литье? Программно сделать изображениеView видимым / невидимым с помощью переменной kotlin Неразрешенная ссылка только для одного унаследованного метода в деле делегирования Изображение существует, но не null, но я получаю исключение NullPointerException Почему Котлин не следил за синтаксисом Java? Пользовательский тип Kotlin Generics с использованием подстановочного знака (число + «Больше 5») Не работает «Ошибка конкатенации» LMAX Disruptor с Kotlin: нельзя использовать лямбда? Kotlin: Внутренний масштаб – этот