You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 20:07:02