我喜歡解決方案@mfulton26建議,它符合這個用法ca非常好。以下答案適用於不能依賴數值類型的情況(例如,T
爲Any
,並且您想確切知道它是什麼,但傳遞給您班級的所有實例都是String
s )。
首先,你不能在一個companion object
有你的類的不同實例的不同值val
,因爲,首先,同伴對象有無關的情況下,它是一個獨立的對象並且獲得其財產不(也不能)涉及其封閉類的實例。看起來像size
應該是一個成員屬性。
但即使是成員的屬性和功能,檢查類型參數T
不能直接做,因爲在科特林泛型是類似於在Java和有type erasure太多,因此在運行時你不能用實際類型參數進行操作。
要做到這一點,您可以根據其存儲在KClass<T>
(或Class<T>
)對象在Vec2t<T>
並實現你的邏輯:
abstract class Vec2t<T : Number>(open var x: T,
open var y: T,
private val type: KClass<T>) {
val size: Int by lazy {
2 * when (type) {
Byte::class -> 1
Short::class -> 2
Int::class, Float::class -> 4
Long::class, Double::class -> 8
else -> throw ArithmeticException("Type undefined")
}
}
}
這就要求子類的參數添加到他們的超類的構造函數調用:
class Vec2(override var x: Float, override var y: Float) : Vec2t<Float>(x, y, Float::class)
如果選擇這種方式,可以科特林還爲您提供reified generics幫忙,所以您可以避免在使用地點明確指定SomeType::class
。例如,如果你的Vec2t<T>
不是抽象的,你可以用這個工廠函數構造它:
inline fun <reified T: Number> vec2t(x: T, y: T) = Vec2t(x, y, T::class)
內聯函數,你僅僅是因爲函數是在調用點內聯,從而可以訪問實際類型參數它的類型參數總是在編譯時被知道。不幸的是,構造函數不能有任何類型參數。
的使用方式:
val i = vec2t(1, 1) // Vec2t<Int> inferred from arguments type Int
println(i.size) // 8
val d = vec2t(1.0, 1.0) // the same but it's Vec2t<Double> this time
println(d.size) // 16
'size'屬性不應位於伴隨對象中。你不能訪問'length()'函數。在創建對象之前,您無法測量其大小。 – marstran
那麼尺寸應該放在哪裏?我發現它可能絕對是靜態的。對不起'length()',它是一個wip。 – elect
@elect,似乎它不應該是靜態的,因爲你希望大小對於Vec2t的不同實例是不同的 - 意味着它的行爲應該根據它所調用的內容而有所不同,絕對不是靜態的行爲。 – hotkey