如何在函数中使用泛型来避免重复代码?

Umu*_*vas 2 generics kotlin

我有一个关于 Kotlin 中泛型的使用的具体问题。

我想创建一个以泛型T作为参数的函数。name它使用它从类之一进行分配:Class1或Class2分配给局部变量testString。

不幸的是,只有当我使用 if 条件检查参数的类型时,这才有可能。

这会导致重复的代码。如果我尝试避免这种情况并使用第 12 行,我会在编译时收到此错误:Unresolved reference: name

当您要使用的类具有相同名称的相同属性时,Kotlin 中是否可以避免 if 条件并仅使用 testString 赋值一次?

代码:

fun main() {
    val class1 = Class1("Foo1")
    val class2 = Class2("Foo2")
}

class Class1(val name: String)
class Class2(val name: String)

fun <T> doStuff(classOneOrTwo: T) {
    var testString: String

    testString = classOneOrTwo.name //not working: Unresolved reference: name

    if (classOneOrTwo is Class1) {
        testString = classOneOrTwo.name
    }
    if (classOneOrTwo is Class2) {
        testString = classOneOrTwo.name
    }
}
Run Code Online (Sandbox Code Playgroud)

Swe*_*per 5

这里不需要泛型。

您可以只编写一个要求其实现者具有name属性的接口。

interface HasName {
    val name: String
}
Run Code Online (Sandbox Code Playgroud)

Class1并且Class2应该实现接口:

class Class1(override val name: String): HasName
class Class2(override val name: String): HasName
Run Code Online (Sandbox Code Playgroud)

那么doStuff可以写成:

fun doStuff(classOneOrTwo: HasName) {
    var testString = classOneOrTwo.name
    // ...
}
Run Code Online (Sandbox Code Playgroud)

您可以通用doStuff:

fun <T: HasName> doStuff(classOneOrTwo: T) {
    var testString = classOneOrTwo.name
    // ...
}
Run Code Online (Sandbox Code Playgroud)

但这样做并不会给你带来任何特别的好处。

当您想要建立某种“链接”时,无论是在参数之间,还是在参数和返回类型之间,非具体化*泛型是最有帮助的。例如,如果您的方法应该返回与它所需要的类型相同的内容:

fun <T> doStuff(foo: T): T { ... }
Run Code Online (Sandbox Code Playgroud)

或者你的方法需要两个参数,第二个参数必须是第一个参数的元素类型,这是一个可变列表:

fun <T> doStuff(list: MutableList<T>, t: T) { ... }
Run Code Online (Sandbox Code Playgroud)

*本段不太适用于具体化泛型,它本身可能很有用。