我想做的是使用可以是其他三种类型之一的泛型类型。
这是一个带有函数的示例:
fun <T> get(key: String) : T where T: String, T: Number, T: Boolean {}
上面的代码不起作用,那我该怎么做呢?
我想做的是使用可以是其他三种类型之一的泛型类型。
这是一个带有函数的示例:
fun <T> get(key: String) : T where T: String, T: Number, T: Boolean {}
上面的代码不起作用,那我该怎么做呢?
这不起作用,因为T
不能表示为位于 、 和 的交集处的String
某种Number
类型Boolean
。
如果您想将您的类型限制为预定义类型的列表,密封类是一个很好的解决方案。
sealed class MyData {
class Bool(val data: Boolean) : MyData()
class String(val data: String) : MyData()
class Number(val data: Number) : MyData()
}
fun get(key: String): MyData = TODO()
对于 KotlinJS,您可以使用ts2kt将您的 TypeScript 定义转换为 Kotlin。它确实支持联合类型,但可能并非所有情况都是完美的。ts2kt 中有针对 unionTypes 的测试,这些测试揭示了它们现在的处理方式,并且您可以在针对 JavaScript 平台时对您手动创建的任何内容执行类似的操作。
问题 #41的评论中提到了进一步的工作- 以添加更好的 Union Type 支持。最后,至少有一个关于该主题的讨论线程表明:
在 JS 和 TS 中,大多数情况下联合类型用作重载的替代方案,因此在不久的将来,我们将尽可能使用重载。此外,我们考虑提供额外的方法来为本地声明指定联合类型。
还有另一个 Stack Overflow 问题正在讨论这个问题,并提供了一些当前选项: Kotlin 和有区别的联合(求和类型),它们的答案在所有 Kotlin 目标平台上都有效。
特别是对于 JavaScript 目标,您可以考虑使用dynamic
type。我在 ts2kt 中看到至少一个使用这种类型的测试用例。这个例子从这个 TypeScript 代码开始:
declare class Foo
type Key = Key2 | number;
type Key2 = string | Foo;
declare var fooKey: Key;
declare function barKey(a: Key|number);
declare function barList(a: List<Key>);
declare function barArray(a: Key[]);
interface Parent {
(...children: Key[]): Foo;
}
dynamic
并使用作为返回类型代替联合类型生成此 Kotlin ;在其他情况下,重载方法签名以处理联合类型(我添加了一些评论):
external open class Foo
// using dynamic in place of union type
external var fooKey: dynamic /* String | Foo | Number */ = definedExternally
// using method overloading in place of union type
external fun barKey(a: String): Unit = definedExternally
external fun barKey(a: Foo): Unit = definedExternally
external fun barKey(a: Number): Unit = definedExternally
// using dynamic in place of union type
external fun barList(a: List<dynamic /* String | Foo | Number */>): Unit = definedExternally
external fun barArray(a: Array<dynamic /* String | Foo | Number */>): Unit = definedExternally
external interface Parent {
// using method overloading in place of union type
@nativeInvoke
fun invoke(vararg children: String): Foo
@nativeInvoke
fun invoke(vararg children: Foo): Foo
@nativeInvoke
fun invoke(vararg children: Number): Foo
}
但同样,您应该查看联合类型的所有 ts2kt 测试用例,以了解其他想法,包括处理undefined
.
在这种情况下,编译器如何知道返回的是什么类型?T
可能是任何东西,所以他们无法定义这样的东西。
您可以定义三种特定于类型的方法:
fun getString(key: String): String = ...
fun getBoolean(key: String): Boolean= ...
fun getInt(key: String): Int = ...
(或包装方法,正如 kevinmost 建议的那样)