如何在Kotlin中声明具有两种类型的变量,例如val x:整数或字符串

bq8i3lrv  于 2022-11-30  发布在  Kotlin
关注(0)|答案(6)|浏览(139)

我将编写一个方法,如下所示:

object UIBehavior {
   fun dialog(context: Context, title: Int | String, message: Int | String){
     val dialogObj = AlertDialog.Builder(context)
     dialogObj.setTitle(title)
     dialogObj.setMessage(message)
   }
}

方法 dialogObj.setTitledialogObj.setMessage 允许两种类型的参数,如何删除可使方法 dialog 仅允许两种类型Int和String的参数?

vmdwslir

vmdwslir1#

在Kotlin你不能这么做。
但是一个函数可以有多个版本,例如:

object UIBehavior {
    fun dialog(context: Context, titleId: Int, messageId: Int){
        val titleString = context.getString(titleId)
        val messageString = context.getString(messageId)
        dialog(context, titleString, messageString)
    }

    fun dialog(context: Context, title: String, message: String) {
        val dialogObj = AlertDialog.Builder(context)
        dialogObj.setTitle(title)
        dialogObj.setMessage(message)
    }
}

这样,您就可以简单地使用id或字符串调用该函数,看起来您正在使用同一个函数

UIBehavior.dialog(this, R.string.title, R.string.message)
UIBehavior.dialog(this, "title", "message")

您还可以使用IntString的公共超类型,但这将允许更多的内容,我不建议这样做。

fun dialog(context: Context, title: Any, messageId: Any){
    val titleString = when (title) {
        is String -> title
        is Int -> context.getString(title)
        else -> throw IllegalArgumentException("Unsupported type")
    }
    val messageString = when ...
       ...
    dialog(context, titleString, messageString)
}

泛型在这里也不起作用,因为你不能动态地调用dialogObj.setTitle(title)。你必须在编译时知道你是想调用Int还是String重载函数。这和使用Any也没有什么不同。

z18hc3ub

z18hc3ub2#

1.泛型可以为您提供解决方案。

fun <T>dialog(context: Context, title: T, message: T){
   if(title !is String && title !is Int) throw InvalidParameterException()
   val dialogObj = AlertDialog.Builder(context)
   dialogObj.setTitle(title)
   dialogObj.setMessage(message)
}

1.使用Any也可以是一个解决方案:

fun dialog(context: Context, title: Any, message: Any){
   if(title !is String && title !is Int) throw InvalidParameterException()
   val dialogObj = AlertDialog.Builder(context)
   dialogObj.setTitle(title)
   dialogObj.setMessage(message)
}
fjaof16o

fjaof16o3#

您可以使用Generics来拥有相同的方法,并检查方法主体中的型别。
或者有两种不同的方法。

omhiaaxx

omhiaaxx4#

您可以使用Any,但我认为这根本不是一个很好的解决方案。
最好将title和message都设置为String或CharSequence,并与setTitle和setMessage作为参数的类型一致。

yuvru6vn

yuvru6vn5#

谢谢你们我在写代码

interface DialogOption {
    val title: Any
    val message: Any
    val positiveBtnTxt: Any
    val negativeBtnTxt: Any
    fun confirm(d: DialogInterface, n: Int) {
        d.dismiss()
    }
    fun cancel(d: DialogInterface, n: Int) {
        d.dismiss()
    }

}

object UIBehavior {
    fun dialog(context: Context, opt: DialogOption) {
        val dialogObj = AlertDialog.Builder(context)
        val title = opt.title
        val message = opt.message
        val poTxt = opt.positiveBtnTxt
        val negTxt = opt.negativeBtnTxt
        fun positiveCallback(d: DialogInterface, n: Int) {
            opt.confirm(d, n)
        }

        fun negativeCallback(d: DialogInterface, n: Int) {
            opt.cancel(d, n)
        }

        if (title is String) {
            dialogObj.setTitle(title)
        } else if (title is Int) {
            dialogObj.setTitle(title)
        }
        if (message is String) {
            dialogObj.setMessage(message)
        } else if (message is Int) {
            dialogObj.setMessage(message)
        }
        if (poTxt is String) {
            dialogObj.setPositiveButton(poTxt, ::positiveCallback)
        } else if (poTxt is Int) {
            dialogObj.setPositiveButton(poTxt, ::positiveCallback)
        }
        if ( negTxt is String) {
            dialogObj.setNegativeButton(negTxt, ::negativeCallback)
        } else if (negTxt is Int) {
            dialogObj.setNegativeButton(negTxt, ::negativeCallback)
        }

        dialogObj.show()
    }
}

可行,但不确定是否合理

cczfrluj

cczfrluj6#

一般解决方案:

我们可以在Kotlin中声明一个具有两种类型的变量,方法是:

代码:

sealed class ABClass<out T>
{
    data class SealedClassA<out ClassA>(val value: ClassA) : ABClass<ClassA>()
    data class SealedClassB<out ClassB>(val value: ClassB) : ABClass<ClassB>()
}

fun main() {

    val a : ClassA = ClassA()
    var b : ClassB = ClassB()
    var s : String = "Just a string"

    var c : ABClass<Any> = ABClass.SealedClassA(a)
    //  c = ABClass.SealedClassB(b) // Works

    //  c = ABClass()               // Error : Sealed types cannot be instantiated
    //  c = ABClass.SealedClassA(s) // Error : class java.lang.String cannot be cast to class Token
    //  c = ABClass.SealedClassB(s) // Error : class java.lang.String cannot be cast to class Break

    when(c)
    {
        is ABClass.SealedClassA -> { println("ABClassClassA ${(c.value as ClassA).AVariable}") }
        is ABClass.SealedClassB -> { println("ABClassClassB ${(c.value as ClassB).BVariable}") }
    }

}

open class ClassA
{
    var AVariable : Int = 1
}
open class ClassB
{
    var BVariable : Int = 10
}

说明:

密封类ABClass具有类型参数T,密封类的后续直接子类(SealedClassA & SealedClassB)被限制为
对于data class SealedClassA
针对data class SealedClassBClassB
因此我们只能有这两种类型。
我们将目标变量初始化为**ABClass<Any>Any**允许存储任何类型的变量,但由于密封类的定义,仅允许存储ClassAClassB
指定为c = ABClass.SealedClassA(a)c = ABClass.SealedClassB(b)
其中,a是ClassA的示例,b是ClassB的示例

使用when表达式。可以验证所有情况,不需要在语句中添加else子句。

因此,变量c基本上只能存储两种类型ClassAClassB

相关问题