Функция Generi c с ограничением и передачей параметра супертипа в Kotlin - PullRequest
0 голосов
/ 02 мая 2020

Я очень плохо знаком с концепцией обобщения, поэтому недавно я наткнулся на некоторую запутанную ситуацию.

Я хочу написать функцию, которая отправляет файл на удаленный сервер. Файл может быть изображением или аудио. Разница в отправке будет заключаться только в том, как мы работаем с параметрами файла (ширина и высота изображения в зависимости от продолжительности звука) и устанавливаем тип сообщения. Поэтому было вполне естественно написать общую функцию для обоих вариантов использования.

Допустим, у меня есть некоторый класс (в данном случае запечатанный класс для простых when проверок), который имеет несколько наследников.

sealed class MessageData

data class MessageAudioData(
    val duration: Float
) : MessageData()

data class MessageImageData(
    var width: Float,
    var height: Float
) : MessageData()

Изначально я хотел написать такую ​​функцию:

fun <T : MessageData> sendFile(fileData: T) {
    ...
}

Но с введением запечатанного класса проверка when не работает, как положено. Поэтому я переписал свою функцию так:

fun sendFile(fileData: MessageData) {
    ...
}

when проверка работает, и у меня, похоже, нет проблем с ней.

Но потом я подумал, верно ли это способ go, и в чем разница. Я читал о дисперсии, и я думаю, что это будет иметь значение в классе (с in и out), но, вероятно, я что-то упускаю. Может ли кто-нибудь помочь мне лучше понять это?

РЕДАКТИРОВАТЬ : Я думаю, что мне нужно немного прояснить ситуацию, так как я слишком много внимания уделяю запечатанному классу.

Меня больше всего интересовало использование и варианты использования обобщенных c функций с ограничениями. О работе именно с типом внутри функции? Я имею в виду, что я могу иметь interface I, а затем class A и class B реализовать этот интерфейс, а затем написать функцию для работы с ними. Кажется, мне не нужно писать шаблон c, я могу просто передать параметр типа I, и он будет работать как с fun example(A()), так и fun example(B()).

1 Ответ

3 голосов
/ 02 мая 2020

Вы используете оператор when для выполнения различных действий в зависимости от типа элемента, передаваемого в функцию. Обобщения не помогут с этим вообще.

Обобщения в основном используются для классов коллекций или типов контейнеров, где вы можете помещать или извлекать вещи, а компилятор гарантирует, что вы правильно интерпретируете типы входить или выходить. Когда дело доходит до функций, если ваша функция не работает с коллекциями или обобщенными c классами-контейнерами, у нее, скорее всего, нет причин иметь универсальный тип c.

Запечатанные классы звучат как подходящие подходит для вашего случая использования, когда у вас есть конечное число типов, это простые классы типов данных, и вы хотите обрабатывать каждый из них по-своему. Традиционно, передача объекта в функцию и проверка его типа, а также приведение и обработка по-разному обычно являются запахом кода, поскольку обычно это можно решить более надежно с помощью полиморфизма (каждый объект обрабатывает свое собственное уникальное поведение). Запечатанные классы могут разрешить риски и хрупкость кода, возникающие в результате проверки типов, путем принудительной обработки всех возможностей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...