Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Kotlin 我们能为一组类型实现编译时类型安全吗';你不能控制吗?_Kotlin - Fatal编程技术网

Kotlin 我们能为一组类型实现编译时类型安全吗';你不能控制吗?

Kotlin 我们能为一组类型实现编译时类型安全吗';你不能控制吗?,kotlin,Kotlin,假设我有一个函数: fun doSomething(vararg pairs: Pair<String, *>) { // Do things with the pairs } 如果受限类型“set”在我的控制下,我可以使用接口或密封类来实现这一点。例如 sealed class Root class Child1 : Root() class Child2 : Root() fun doSomethingICanControl(param: Root) { //

假设我有一个函数:

fun doSomething(vararg pairs: Pair<String, *>) {
    // Do things with the pairs
}
如果受限类型“set”在我的控制下,我可以使用接口或密封类来实现这一点。例如

sealed class Root
class Child1 : Root()
class Child2 : Root()

fun doSomethingICanControl(param: Root) {
    // Root implementation
}
然而,如果我不能控制类型或者它们是基本类型,我如何防止
*
允许所有内容通过呢

我知道我可以使用智能强制转换来获得运行时安全性,但这可以在编译时完成吗

还是语言不允许

编辑1

我知道我可以创建自己的框类型(例如,
MyBoolean
),并使用公共接口或密封类,但这将是每个人都必须在每次需要时编写的样板文件

编辑2

说清楚,我希望能够这样做:

doSomething(
    "key1" to false,
    "key2" to "value2",
    "key3" to 86
)

。。。也就是说,有一组混合的“第二”(of
Pair
)类型。

因此,快速总结:

您想从需要
对的库中调用方法,
但是要限制
*
可能的值

TL;DR:如果没有某种包装,你想要完成的事情是不可能的,因为

  • Kotlin中没有求和类型,因此无法告诉编译器您期望的是Int、Double或Float,而不是其他类型
  • 如果库方法希望某个对象是
    Pair
    ,那么我们无法告诉编译器,我们只想给它一个
    字符串,而不是
    *
  • 获得这种行为的一种方法是创建一个Decorator(),例如,创建您自己的扩展方法,它只允许一个子集

    class Foo {
        //Allows everything
        fun doSomething(param: Pair<String, *>)
    }
    
    //Now lets create our own extension methods
    fun Foo.doSomethingWithInt(param: Pair<String, Int>)
    
    fun Foo.doSomethingWithBoolean(param: Pair<String, Boolean>)
    
    fun Foo.doSomethingWithString(param: Pair<String, String>)
    
    如果没有某种包装器,下面的示例是不可能的,因为Kotlin中没有Sum类型:

    doSomething(
        "key1" to false,
        "key2" to "value2",
        "key3" to 86
    )
    
    你能做的是:

    首先,创建您自己的
    jsonim
    类型,并将扩展方法添加到可以用作扩展方法的类型中

    class JSONItem<T> private constructor (item: T)
    
    fun Int.asJSONItem() = JSONItem(this)
    
    fun String.asJSONItem() = JSONItem(this)
    
    fun Boolean.asJSONItem() = JSONItem(this)
    
    类JSONItem私有构造函数(项:T)
    fun Int.asJSONItem()=JSONItem(this)
    fun String.asjsonim()=jsonim(this)
    fun Boolean.asjsonim()=jsonim(this)
    
    然后你就可以这样做了:

    //Your own personal doSomething
    fun doSomething(varargs: param: Pair<String, JSONItem>) { 
        //Call the real doSomething()
        doSomething(param.map { Pair(it.first, it.second.item) }}
    }
    
    doSomething(
        "key1" to false.asJSONItem(),
        "key2" to "value2".asJSONItem(),
        "key3" to 86.asJSONItem()
    )
    
    //你自己的个人资料
    fun doSomething(varargs:param:Pair){
    //称为真正的doSomething()
    doSomething(param.map{Pair(it.first,it.second.item)}
    }
    剂量(
    将“key1”改为false.asjsonim(),
    “键2”到“值2”。asJSONItem(),
    “键3”到86.asJSONItem()
    )
    
    Kotlin(从1.1.x开始)目前不支持可指示的并集和交叉点类型


    是相关问题。

    标记接口是实现这一点的唯一方法。对于您无权访问的类(例如int)你可以自己把它框起来。自我删除我的答案,因为编辑2使它无效。你能再详细一点吗?doSomething是你调用的库的方法吗?还是库调用你的doSomething?@D3xter是我调用的库,例如Kotson的
    jsonObject()
    您的
    Foo
    扩展重载将无法编译,因为您没有使用不同的JVM名称对它们进行注释。至于您的
    .asjsonim()
    方法,这还不错。我只是想知道该语言是否能够在没有重复样板的情况下处理此问题,而目前似乎无法。
    class JSONItem<T> private constructor (item: T)
    
    fun Int.asJSONItem() = JSONItem(this)
    
    fun String.asJSONItem() = JSONItem(this)
    
    fun Boolean.asJSONItem() = JSONItem(this)
    
    //Your own personal doSomething
    fun doSomething(varargs: param: Pair<String, JSONItem>) { 
        //Call the real doSomething()
        doSomething(param.map { Pair(it.first, it.second.item) }}
    }
    
    doSomething(
        "key1" to false.asJSONItem(),
        "key2" to "value2".asJSONItem(),
        "key3" to 86.asJSONItem()
    )