Kotlin泛型FileMarshaller工厂返回类型如何处理?
解决方案
方案一:使用无界通配符FileMarshaller<*>
这是最直接的处理方式,把工厂方法的返回类型设为通配符形式,虽然会丢失部分编译时类型安全,但可以快速解决返回类型的问题。
class FileMarshallerFactory { internal fun createMarshaller(fileType: FileTypes): FileMarshaller<*> { return when (fileType) { FileTypes.DOCUMENT -> DocumentFileMarshaller() else -> throw MarshallerNotFound(MARSHALLER_NOT_FOUND) } } }
调用时需要手动做类型转换,确保传入对象的类型匹配:
val marshaller = factory.createMarshaller(FileTypes.DOCUMENT) as FileMarshaller<Document> marshaller.marshal(documentInstance)
方案二:泛型化工厂方法(类型安全)
通过给工厂方法添加reified泛型参数,结合inline关键字,让调用方可以指定目标类型,同时在内部完成类型与FileTypes的映射,既保留编译时类型安全,又不用手动转换。
首先给枚举类添加类型关联:
enum class FileTypes { DOCUMENT; val targetType: KClass<*> get() = when (this) { DOCUMENT -> Document::class } }
然后改造工厂类:
class FileMarshallerFactory { // 供外部调用的类型安全方法 inline fun <reified T> createMarshaller(): FileMarshaller<T> { val fileType = when (T::class) { Document::class -> FileTypes.DOCUMENT else -> throw MarshallerNotFound(MARSHALLER_NOT_FOUND) } return createMarshaller(fileType) as FileMarshaller<T> } // 内部实现方法,返回通配符类型 internal fun createMarshaller(fileType: FileTypes): FileMarshaller<*> { return when (fileType) { FileTypes.DOCUMENT -> DocumentFileMarshaller() else -> throw MarshallerNotFound(MARSHALLER_NOT_FOUND) } } }
调用时直接指定泛型类型即可:
val marshaller = factory.createMarshaller<Document>() marshaller.marshal(documentInstance)
方案三:调整接口设计(放弃泛型)
如果可以接受运行时类型检查,可以去掉接口的泛型,把类型判断逻辑放到具体实现类内部,这样工厂方法的返回类型就无需泛型参数。
改造后的接口与实现类:
interface FileMarshaller { fun marshal(obj: Any): File fun supports(obj: Any): Boolean // 用于判断当前Marshaller是否支持该对象 } internal class DocumentFileMarshaller : FileMarshaller { override fun marshal(obj: Any): File { val document = obj as Document // 运行时类型转换 // XML序列化逻辑 } override fun supports(obj: Any): Boolean { return obj is Document } }
工厂类简化为:
class FileMarshallerFactory { internal fun createMarshaller(fileType: FileTypes): FileMarshaller { return when (fileType) { FileTypes.DOCUMENT -> DocumentFileMarshaller() else -> throw MarshallerNotFound(MARSHALLER_NOT_FOUND) } } }
调用时先通过supports确认类型,再执行序列化:
val marshaller = factory.createMarshaller(FileTypes.DOCUMENT) if (marshaller.supports(documentInstance)) { marshaller.marshal(documentInstance) }
内容的提问来源于stack exchange,提问作者Pelicer
相关产品推荐
相关产品推荐

