我们说我有一个功能:
fun doSomething(vararg pairs: Pair<String, *>) {
// Do things with the pairs
}
这种方法的问题在于它允许Pair
的后半部分的任何类型(例如Pair<String, CustomType1>
)。
如果我只想允许有限数量的类型,我将如何实现呢?
如果函数具有更简单的签名,我可以通过重载实现限制,如下所示:
fun doSomethingSimpler(param: Boolean) {
// Boolean implementation
}
fun doSomethingSimpler(param: Int) {
// Int implementation
}
// etc.
如果限制类型&#34;设置&#34;在我的控制下,我可以使用界面或密封类来实现这一目标。 E.g。
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
)
...... I.e。有一组混合的&#34;秒&#34; (Pair
)种类。
答案 0 :(得分:2)
所以快速总结一下:
您想从期望Pair<String, *>
的库中调用方法,
但限制*
可能的值。
TL; DR:没有某种包装器,你想要实现的目标是不可能的,因为
Pair<String, *>
,我们就无法告诉编译器,我们只希望能够给它一个String
而不是{{1 }} 获得该行为的一种方法是创建一个装饰器(Decorator Pattern),例如创建自己的扩展方法,只允许子集
*
或者如果你不想打电话给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>)
你
可以创建Decoractor-Class:
Foo.doSomething()
如果没有某种Wrapper,以下示例是不可能的,因为Kotlin中没有Sum-Types:
class FooDecorator {
val foo = Foo()
fun doSomething(param: Pair<String, Int>) { }
}
你可以做的是:
首先,创建您自己的doSomething(
"key1" to false,
"key2" to "value2",
"key3" to 86
)
类型,并将扩展方法添加到可用作其中的类型
JSONItem
然后你可以做那样的事情:
class JSONItem<T> private constructor (item: T)
fun Int.asJSONItem() = JSONItem(this)
fun String.asJSONItem() = JSONItem(this)
fun Boolean.asJSONItem() = JSONItem(this)
答案 1 :(得分:0)
Kotlin目前不支持可表示的并集和交集类型(从1.1.x开始)。
This是相关问题。