Generics 如何使用多个参数化类型(使用where子句),以便可以使用任一参数
有没有办法告诉kotlin此函数接受的类型T可以是Long、Int或String 在本例中,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 {
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"
}