我有一個關于在 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
}
}
uj5u.com熱心網友回復:
你在這里不需要泛型。
你可以只寫一個介面,要求它的實作者有一個name屬性。
interface HasName {
val name: String
}
Class1并且Class2應該實作介面:
class Class1(override val name: String): HasName
class Class2(override val name: String): HasName
那么doStuff可以寫成:
fun doStuff(classOneOrTwo: HasName) {
var testString = classOneOrTwo.name
// ...
}
你可以通用doStuff:
fun <T: HasName> doStuff(classOneOrTwo: T) {
var testString = classOneOrTwo.name
// ...
}
但是你這樣做并沒有什么特別的收獲。
當你想建立某種“鏈接”時,非具體化*泛型是最有幫助的,無論是在引數之間,還是在引數和回傳型別之間。例如,如果你的方法應該回傳與它所需要的相同型別的東西:
fun <T> doStuff(foo: T): T { ... }
或者你的方法有兩個引數,第二個引數必須是第一個引數的元素型別,是一個可變串列:
fun <T> doStuff(list: MutableList<T>, t: T) { ... }
*本段并不完全適用于具體化的泛型,它們本身可能很有用。
uj5u.com熱心網友回復:
Class1并且Class2doStuff 函式沒有任何共同點來決議屬性name,即使它們是以完全相同的方式撰寫的,如果你期望僅僅因為你有一個通用引數,那么T一切都會被自動決議,不幸的是編譯器不知道什么T是在這里,除了它是隱Any?式型別之外,(即<T: Any?>)。
您在這里遇到編譯錯誤,name因為它不是Any?
classOneOrTwo.name //not working: Unresolved reference: name
但是,呼叫 doStuff 函式編譯得很好,因為 Kotlin 中的所有內容都是 Any?
fun main() {
val class1 = Class1("Foo1")
val class2 = Class2("Foo2")
doStuff(class1)
doStuff(class2)
}
如果你嘗試使用classOneOrTwoparam 呼叫某個函式并按下cltr click它,你會看到它是一個型別的函式Any?
fun <T> doStuff(classOneOrTwo: T) {
...
...
classOneOrTwo.toString() // <-- ctrl click this you'll see its a function of Any?,
在您的情況下,您應該創建一個層次結構 ( Inheritance)Class1并且Class2可以從中繼承某些東西name
open class ParentClass(open val name: String)
class Class1(override val name: String) : ParentClass(name)
class Class2(override val name: String) : ParentClass(name)
fun <T: ParentClass> doStuff(classOneOrTwo: T) {
Log.e("DoStuff", classOneOrTwo.name) // now this works find because
}
現在它起作用了,因為您明確告訴編譯器這是屬性存在位置T的型別,并且由您的and繼承。ParentClassnameClass1Class2
回到你的主要功能
doStuff(class1)
doStuff(class2)
印刷,
Foo1
Foo2
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/525662.html
標籤:科特林仿制药
上一篇:未實作特征時回傳泛型
