我有一个场景,需要将对象编码为 XML。该对象可以是多个类型,因此我创建了一个接口(interface),将该对象类型设置为通用 T。
interface FileMarshaller<T> {
fun marshal(object: T): File
}
我将有这个接口(interface)的几种实现,每种类型的对象都有一个实现。这是一个:
internal class DocumentFileMarshaller : FileMarshaller<Document> {
override fun marshal(document: Document): File {
//some kotlin code
}
}
这很好,满足我的需要。问题出在工厂。该工厂接收一个参数并根据该参数决定应检索哪个编码器。
class FileMarshallerFactory {
internal fun createMarshaller(fileType: FileTypes): FileMarshaller<What should I put here?> {
when (fileType) {
FileTypes.DOCUMENT -> {
return DocumentFileMarshaller()
}
else -> throw MarshallerNotFound(MARSHALLER_NOT_FOUND)
}
}
}
问题出在工厂的返回类型上。我不能将其留空,我不能将 Document 作为它的类型,因为我将有更多的实现。我该如何处理这个类型参数?也许除了我创建的这个工厂之外还有另一种方法?
最佳答案
在您的情况下,FileTypes
确定结果类型是什么,并且它始终与特定类型相关,因此对其进行参数化也是有意义的。然后将其用作T
的“源”:
class FileMarshallerFactory {
@Suppress("UNCHECKED_CAST")
internal fun <T> createMarshaller(fileType: FileTypes<T>): FileMarshaller<T> {
when (fileType) {
FileTypes.DOCUMENT -> {
return DocumentFileMarshaller() as FileMarshaller<T>
}
else -> throw MarshallerNotFound(MARSHALLER_NOT_FOUND)
}
}
}
sealed interface FileTypes<T> {
object DOCUMENT : FileTypes<Document>
}
请注意,这种方法不能使用枚举。您需要一个密封的接口(interface)/类。
而且,说实话,这个代码设计让我感觉有点奇怪。如果编码器的数量有限,并且调用者需要知道它到底获取了哪个编码器,则它必须知道 Document
和 FileTypes.DOCUMENT
,然后就不会'为每个编码器建立单独的工厂不是更容易吗?要么通过多个函数,要么通过完全独立的类。也许这是因为我们看到的不是完整的图片,而是一个简化的示例。
关于Kotlin 接口(interface)类型参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75620439/