我可以通过类型信息来简化这个吗?
我有很多类似这样的代码,除了类型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) } }
你可以用泛型来做你想做的事情。 但是,要使用泛型,我们首先需要将这个巨大的代码块提取到一个方法中:
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) } }
最后一件事:请注意,在我所有的例子中,我使用了属性getters( get() = ...
)和原始代码一样。 不过,我强烈怀疑你不想使用吸气剂。 每次有人访问您的财产时,都会调用Getters,在这种情况下,每次有人读取positions
属性时,您都会调用constructServiceURL
并进行服务调用等。如果您希望代码只发生一次,那么您应该只需调用一次getArrayOf()
并将结果赋给您的属性:
val positions: Array<PositionJson>? = getArrayOf() // this syntax would also work: val positions = getArrayOf<PositionJson>()