简体   繁体   English

Kotlin:如何将集合传递给函数的泛型类型

[英]Kotlin: how to pass collection into generic type of a function

I have this abstract function: 我有这个抽象的功能:

    abstract fun <T> updateValue(value: T)

Now i want a subclass to override it with a collection into the generic type: 现在我想要一个子类用泛型类型的集合覆盖它:

override fun <List<Int>> updateValue(value: List<Int>)

and this does not work. 这不起作用。 Basic types work just fine (String, Int etc) but when I want to use a collection I do not know the right syntax. 基本类型工作得很好(String,Int等),但是当我想使用集合时,我不知道正确的语法。 This is ok: 还行吧:

override fun <String> updateValue(value: String)

You cannot override a generic function with a fixed parameter, instead, you may have the type parameter on a class or interface to make it. 您不能使用固定参数覆盖泛型函数,而是可以在类或接口上使用type参数来创建它。 Eg 例如

abstract class BaseClass<T> {
  abstract fun updateValue(value: T) : Unit
}

///class to accept _only_ List<Int>
class ListClass<List<Int>> {
  override fun updateValue(value: List<Int>) { /*...*/ }
}

/// class to accept _only_ String
class StringClass<String> {
  override fun updateValue(value: String) { /*...*/ }
}

The rationale is as follows when you declare a generic function, eg fun <T> updateValue(value: T) is mean it is supposed to work for every possible T . 当你声明一个泛型函数时,基本原理如下,例如fun <T> updateValue(value: T)意味着它应该适用于每个可能的T It will not do a pattern matching to find the best suitable match. 它不会进行模式匹配以找到最合适的匹配。

You may try checking types in the implementation of the generic function to support a specific case, but in general, it could be hard for collection classes because of type erasure . 您可以尝试检查泛型函数的实现中的类型以支持特定情况,但一般来说,由于类型擦除 ,集合类可能很难。

fun <T> updateValue(value: T) {
  when (value) {
    is String -> handleStringValue(value)
    is List<*> -> handleListValue(value)
    else -> handleDefault(value)
  }
}

You cannot tell List<Int> from List<String> here. 您无法在此处List<String> List<Int> An inline fun with reified generics may help . 使用reified泛型的inline fun可能会有所帮助

It seems like you'd actually want to use a generic parameter on the class instead: 看起来你真的想在类上使用泛型参数:

abstract class Parent<T> {
    abstract fun updateValue(value: T)
}

And then extend it to: 然后将其扩展为:

class Child : Parent<List<Int>> {
    override fun updateValue(value: List<Int>)
}

The only reason that the override with String works 使用String覆盖的唯一原因

override fun <String> updateValue(value: String)

is that String is not a type in this context but the name of the generic parameter you used to name T before. String在此上下文中不是类型,而是之前用于命名T的泛型参数的名称。 List<Int> however is not a valid name. List<Int>但不是有效名称。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM