Возвращает подтип, используемый, когда функция расширения установлена для супертипа

#kotlin #generics

#kotlin #общие

Вопрос:

Я создаю контроллер kotlin rest, где я хочу, чтобы разные подтипы коллекций возвращались с разными вызовами. У меня также есть объект Dao, который я хочу сопоставить с Dto для отправки клиенту.

Поэтому у меня есть функция расширения

 private fun Collection<Dao>.toDto(): Collection<Dto> {
    return this.map { dao -> Dto.convertToDto(dao) }
}
 

Однако это вернет a Collection<Dto> независимо от типа коллекции, в которой он используется. Т.Е. На самом деле происходит следующее

 Set<Dao>.toDto() -> Collection<Dto>
List<Dao>.toDto() -> Collection<Dto>
 

Желаемый результат будет

 Set<Dao>.toDto() -> Set<Dto>
List<Dao>.toDto() -> List<Dto>
 

Итак, вопрос состоит из двух частей.

  1. Как мне добиться этого?
  2. это уже приемлемо? Я считаю, что функциональность набора / списка уже будет реализована, не уверен, поддерживает ли collection порядок списка, также это неясно для любых разработчиков, взаимодействующих с API относительно намерения API, чтобы вы получили упорядоченный список или набор и т. Д. Если это не опасно / плохая практика, я мог бы принять это.

Комментарии:

1. Я предполагаю, что вам придется создать несколько функций расширения для разных подклассов коллекции, которые вы хотите использовать.

2. Это нормально для моего варианта использования. Я полагаю, что если у вас есть большое количество подтипов, о которых вы заботитесь, это не будет удовлетворительным решением.

3. Сигнатура функции должна быть примерно такой private fun <T : Collection<*>> T<Dao>.toDto(): T<Dto> , но этот синтаксис невозможен в Kotlin, потому Type arguments are not allowed for type parameters что (кстати, это запрещено и в Java). Но даже если бы это было возможно, map метод всегда возвращает List (сохраняя исходный порядок), независимо от исходного типа коллекции, поэтому вам пришлось бы преобразовать его обратно в исходный подтип коллекции, а в общем случае это невозможно сделать.