Generics 如何使用多个参数化类型(使用where子句),以便可以使用任一参数

Generics 如何使用多个参数化类型(使用where子句),以便可以使用任一参数,generics,kotlin,Generics,Kotlin,有没有办法告诉kotlin此函数接受的类型T可以是Long、Int或String 在本例中,map:map?可以接收一个map import android.content.Context import android.content.Intent const val KEY_COMMAND = "KEY_COMMAND" const val KEY_EXTRA = "KEY_EXTRA" class IntentBuilder { companion object {

有没有办法告诉kotlin此函数接受的类型T可以是Long、Int或String

在本例中,
map:map?
可以接收一个map

import android.content.Context
import android.content.Intent

const val KEY_COMMAND = "KEY_COMMAND"
const val KEY_EXTRA = "KEY_EXTRA"

class IntentBuilder {
    companion object {

        fun <T> getIntent(
            context: Context,
            clazz: Class<Any>,
            command: Command,
            map: Map<String, T>?
        ): Intent where T : Long {
            val intent = Intent(context, clazz)
            intent.putExtra(KEY_COMMAND, command)
            if (map != null) {
                map.entries.forEach {
                    intent.putExtra(it.key, it.value)
                }
            }
        }
    }
}
导入android.content.Context
导入android.content.Intent
const val KEY_COMMAND=“KEY_COMMAND”
const val KEY_EXTRA=“KEY_EXTRA”
类IntentBuilder{
伴星{
娱乐目的(
上下文:上下文,
克拉兹:同学们,
命令:命令,,
地图:地图?
):T:Long{
val intent=intent(上下文,clazz)
intent.putExtra(按键命令,命令)
if(map!=null){
map.entries.forEach{
intent.putExtra(it.key,it.value)
}
}
}
}
}
我想允许此函数接收
Map
Map

因此,
intent.putExtra(it.key,it.value)
不会在编译错误中使用


我认为可以使用where来实现这一点。

您可以通过使用私有构造函数将
getIntent
封装在泛型类中,并提供使用可接受类型参数化的实例来解决问题:

class IntentFactory<in T> private constructor() {
    companion object {
        val int = IntentFactory<Int>()
        val long = IntentFactory<Long>()
        val string = IntentFactory<String>()
    }

    fun getIntent(
        context: Context,
        clazz: Class<*>,
        command: Command,
        map: Map<String, T>?
    ): Intent {
        // your implementation
    }
}
UPD: 如果您的意思是map可以同时包含
Int
Long
String
值,那么应该创建一个类来包装这些类型的对象。我还建议将
key
属性添加到此类:

class IntentExtra<out T> private constructor(val key: String, val value: T) {
    companion object {
        operator fun invoke(key: String, value: Int) = IntentExtra(key, value)
        operator fun invoke(key: String, value: Long) = IntentExtra(key, value)
        operator fun invoke(key: String, value: String) = IntentExtra(key, value)
    }
}
您还可以创建DSL,使客户端代码更干净:

class IntentExtraDSL(private val intent: Intent) {
    private fun extra(key: String, value: Any) {
        intent.putExtra(key, value)
    }

    infix fun String.extra(value: Int) = extra(this, value)
    infix fun String.extra(value: Long) = extra(this, value)
    infix fun String.extra(value: String) = extra(this, value)
}

我不这么认为。我使用,并像这样称呼它:
start(MyKotlinClass::class){putExtra(…);putExtra(…)}
是的,这是可以做到的,我使用了Map.Entry使用there值作为Map Entry,there值可以很容易地使用。还有一个stackoverflow问题:您可以有多个上限,但它们必须同时满足,这意味着
T
必须是
Int
String
的子类型,而不是“or”。谢谢,但我认为它应该有一个更简单的选项
fun getIntent(
    context: Context,
    clazz: Class<*>,
    command: Command,
    extra: List<IntentExtra<*>>?
): Intent {
    // your implementation
}
IntentFactory.getIntent(
    context,
    clazz,
    command,
    listOf(
        IntentExtra("int", 1),
        IntentExtra("long", 1L),
        IntentExtra("string", "s")
    )
)
class IntentExtraDSL(private val intent: Intent) {
    private fun extra(key: String, value: Any) {
        intent.putExtra(key, value)
    }

    infix fun String.extra(value: Int) = extra(this, value)
    infix fun String.extra(value: Long) = extra(this, value)
    infix fun String.extra(value: String) = extra(this, value)
}
fun getIntent(
    context: Context,
    clazz: Class<*>,
    command: Command,
    extra: IntentExtraDSL.() -> Unit
): Intent {
    val intent = Intent(context, clazz)
    intent.putExtra(KEY_COMMAND, command)
    IntentExtraDSL(intent).extra()
    return intent
}
IntentFactory.getIntent(
    context,
    clazz,
    command
) {
    "int" extra 1
    "long" extra 1L
    "string" extra "s"
}