2

我想做的是使用可以是其他三种类型之一的泛型类型。

这是一个带有函数的示例:

fun <T> get(key: String) : T where T: String, T: Number, T: Boolean {}

上面的代码不起作用,那我该怎么做呢?

4

3 回答 3

9

这不起作用,因为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()
于 2017-06-06T16:50:21.680 回答
2

对于 KotlinJS,您可以使用ts2kt将您的 TypeScript 定义转换为 Kotlin。它确实支持联合类型,但可能并非所有情况都是完美的。ts2kt 中有针对 unionTypes 的测试,这些测试揭示了它们现在的处理方式,并且您可以在针对 JavaScript 平台时对您手动创建的任何内容执行类似的操作。

问题 #41的评论中提到了进一步的工作- 以添加更好的 Union Type 支持。最后,至少有一个关于该主题的讨论线程表明:

在 JS 和 TS 中,大多数情况下联合类型用作重载的替代方案,因此在不久的将来,我们将尽可能使用重载。此外,我们考虑提供额外的方法来为本地声明指定联合类型。

还有另一个 Stack Overflow 问题正在讨论这个问题,并提供了一些当前选项: Kotlin 和有区别的联合(求和类型),它们的答案在所有 Kotlin 目标平台上都有效。

特别是对于 JavaScript 目标,您可以考虑使用dynamictype。我在 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.

于 2017-06-06T23:25:58.050 回答
1

在这种情况下,编译器如何知道返回的是什么类型?T可能是任何东西,所以他们无法定义这样的东西。

您可以定义三种特定于类型的方法:

fun getString(key: String): String = ...
fun getBoolean(key: String): Boolean= ...
fun getInt(key: String): Int = ...

(或包装方法,正如 kevinmost 建议的那样)

于 2017-06-06T16:49:00.373 回答