我可以通过类型信息来简化这个吗?

我有很多类似这样的代码,除了类型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>()