我有很多像这样的代码,除PositionJson
类型外,它们都是相同的,可以是AnotherJson
或FooJson
或BarJson
有没有什么方法可以将所有这些代码扩展到一个函数中,我可以以某种方式将其传递给它类型?所以我没有几个几乎完全相同的代码乱丢我的班级?
我不确定这是否可能,只是想我会问,因为这样做会很好......
/**
* @return the _open_ [PositionJson]s
*/
val positions: Array<PositionJson>?
@Throws(AccountsAPIException::class)
get() {
val service = constructServiceURL(POSITIONS, null, true)
try {
val messageJson = mapper.readValue<MessageJson<Array<PositionJson>>>(
callURL(service),
object: TypeReference<MessageJson<Array<PositionJson>>>() {
})
val error = messageJson.error
if (error != null) throw AccountsAPIException(error.errorCode, error.description)
return messageJson.data
} catch (e: Exception) {
throw AccountsAPIException(e)
}
}
答案 0 :(得分:2)
你可以用泛型做你想做的事。但是,要使用泛型,我们首先需要将这个巨大的代码块提取到一个方法中:
val positions: Array<PositionJson>? get() = getPositions()
fun getPositions(): Array<PositionJson>? {
...
}
我们还没有解决问题,但现在我们能够通过使getPositions
通用来解决它(注意我也重命名了这个函数):
val positions: Array<PositionJson> get() = getArrayOf<PositionJson>()
// thanks to type inference I can omit the type on getArrayOf if desired:
val positions: Array<PositionJson> get() = getArrayOf()
fun <T> getArrayOf(): Array<T>? {
val service = constructServiceURL(POSITIONS, null, true)
try {
val messageJson = mapper.readValue<MessageJson<Array<T>>>(
callURL(service),
object: TypeReference<MessageJson<Array<T>>>() {
})
val error = messageJson.error
if (error != null) throw AccountsAPIException(error.errorCode, error.description)
return messageJson.data
} catch (e: Exception) {
throw AccountsAPIException(e)
}
}
完美!由于类型擦除,这将无法编译。但我们也可以通过创建函数inline
并创建类型参数reified
来解决这个问题:
inline fun <reified T: Any> getArrayOf(): Array<T>? {
...
}
那应该这样做。现在您可以根据需要重用此功能:
val positions: Array<PositionJson>? get() = getArrayOf()
val persons: Array<PersonJson>? get() = getArrayOf()
val bananas: Array<BananaJson>? get() = getArrayOf()
inline fun <reified T: Any> getArrayOf(): Array<T>? {
val service = constructServiceURL(POSITIONS, null, true)
try {
val messageJson = mapper.readValue<MessageJson<Array<T>>>(
callURL(service),
object: TypeReference<MessageJson<Array<T>>>() {
})
val error = messageJson.error
if (error != null) throw AccountsAPIException(error.errorCode, error.description)
return messageJson.data
} catch (e: Exception) {
throw AccountsAPIException(e)
}
}
最后一件事:请注意,在我的所有示例中,我使用了属性getter(get() = ...
),就像在原始代码中一样。但是,我强烈怀疑你不想使用吸气剂。每次有人访问您的财产时都会调用Getter,在这种情况下,每次有人读取您将要调用的positions
属性constructServiceURL
并拨打服务电话等时都会调用。如果您需要代码只发生一次然后您应该只调用getArrayOf()
一次并将结果分配给您的属性:
val positions: Array<PositionJson>? = getArrayOf()
// this syntax would also work:
val positions = getArrayOf<PositionJson>()