Просто помните, что информация об универсальном типе стирается во время выполнения, и всякий раз, когда вы пытаетесь поместить что-то в метод, который принимает обобщенные элементы, принимается общий знаменатель, например:
listOf("one", 123) // -> assumes T:Any and therefore gives List<Any>
Теперь для вашего примера этобудет означать, что "one".isNullOr(123)
оба станут Any
.
Однако в качестве идентификатора, если вы объявите определенный тип (например, List<String>
), как показано ниже, он не будет работать, чтобы назначить ему другой тип:
val test : List<String> = listOf(123) // this will not work
Уже во время компиляции известно, что данный int не может стать строкой.Однако этот пример не поможет, так как вы не возвращаете этот универсальный тип.Если ваш метод выглядел немного иначе, например, имел бы универсальный тип в качестве возвращаемого значения, он мог бы легко сработать аналогично примеру List
.
Так что, чтобы исправить ваш пример, вам нужно указатьтип, который в основном сделает infix
устаревшим, например, следующее будет работать так, как вы ожидаете:
val someString : String? = TODO()
val works = someString.isNullOr<String?>("other")
val doesntWork = someString.isNullOr<Int?>(123) // does not nor does:
val doesntWorkToo = someString.isNullOr<String?>(123)
Обратите внимание, что для того, что вы показали, некоторые стандартные функции могут помочь вам (но не устранят эту конкретнуюпроблема), т.е. с использованием ?:
(оператор Элвиса) с ?.let
:
val someVal : String? = "someString given from somewhere"
val thisWorks = someVal?.let {
it == "some other string to compare"
} ?: true /* which basically means it was null */
val thisWillNot = someVal?.let {
it == 123 // compile error (funny enough: it.equals(123) would work ;-)
} ?: true /* it is null */