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()
)