Котлин: функция, которая возвращает универсальный тип. Что если я не знаю, какой конкретный тип должен быть возвращен? - PullRequest
1 голос
/ 23 октября 2019

У меня есть следующий тип:

class Images<T : Image>(
    val images: List<T>,
    val totalCount: Int
)

Так что список здесь может содержать только объекты, которые наследуются от Image.

Теперь у меня есть интерфейс:

interface ImageService<T : Image> {
    fun getNewImages(offset: Int, limit: Int): Images<T>

    fun getNextImage(): Image
}

И конкретная реализация:

class NumberImageService : ImageService<NumberImage> {
    override fun getNewImages(offset: Int, limit: Int): Images<NumberImage> {
        // return something
    }

    override fun getNextImage(): NumberImage {
        // return something
    }
}

Пока все хорошо. Теперь у меня есть другой класс, где я решаю, какую конкретную реализацию использовать на основе ввода enum:

class ImageQueryResolver : GraphQLQueryResolver {
    fun getNewImages(input: ImageInput, offset: Int, limit: Int = Int.MAX_VALUE): Images {
        return when (input.imageType) {
            ImageEnum.NUMBER ->
                numberImageService.getNewImages(offset, limit)
            ImageEnum.LETTER ->
                letterImageService.getNewImages(offset, limit)
        }
    }

    fun getNextImage(input: ImageInput): Image {
        // return something
    }
}

Так что это дает мне ошибку, потому что тип возвращаемого значения getNewImages, который Images требуетиметь аргумент:

One type argument expected for class Images<T : Image>

Но какой аргумент мне нужно использовать сейчас?

Ответы [ 3 ]

2 голосов
/ 23 октября 2019

Вам необходимо указать этот аргумент, поскольку изображения являются общими. Итак, я хотел бы предложить один из двух:

1) Images<out Image> -> тип возвращаемого значения является подтипом Image

2) Images<*> -> Мне все равно, какой универсальный тип существует

Я думаю, что первое решение лучше (мы ограничили это значение, поэтому мы больше знаем, что происходит, все);)

2 голосов
/ 23 октября 2019

Как я уже упоминал в комментарии, вы можете использовать Images<out Image> в качестве типа возврата. Это в основном говорит, что реализация может использовать Image или подтип Image. Если вы знакомы с Java, то это похоже на использование Images<? extends Image>.

Поскольку ваш Images интерфейс создает только объекты типа T, другой вариант - использовать объявление-сайт-дисперсию вместо use-site дисперсия . Другими словами, вы можете иметь:

interface Images<out T : Image> {
    // methods...
}

, что позволит вам использовать Images<Image> в качестве типа возвращаемого значения:

fun getNewImages(input: ImageInput, offset: Int, limit: Int = Int.MAX_VALUE): Images<Image> {
    return when (input.imageType) {
        ImageEnum.NUMBER ->
            numberImageService.getNewImages(offset, limit)
        ImageEnum.LETTER ->
            letterImageService.getNewImages(offset, limit)
    }
}

Вот ссылка на дженерики в Kotlin:https://kotlinlang.org/docs/reference/generics.html

0 голосов
/ 23 октября 2019

Попробуйте это:

fun <T : Image> getNewImages(input: ImageInput, offset: Int, limit: Int = Int.MAX_VALUE): Images<T> {
  return when (input.imageType) {
    ImageEnum.NUMBER ->
      numberImageService.getNewImages(offset, limit)
    ImageEnum.LETTER ->
      letterImageService.getNewImages(offset, limit)
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...