【问题标题】:Object conversion using generics使用泛型进行对象转换
【发布时间】:2020-04-12 02:17:31
【问题描述】:

我确实有一个对象转换任务让我心烦意乱;) 假设,我有三种(或更多)格式的业务对象

class MapA { /*some implementation */ }

class MapB { /*some implementation */ }

class MapC { /*some implementation */ }

此外,我还有一个“超级对象”,它存储在数据库中,包含 MapA、MapB 和 MapC 的所有属性的超集。

class SuperMap { /* all implemented properties from all maps */ }

我现在需要能够在任何地图类型之间进行转换。所以我的想法是指定一个特定的Converter接口,将特定的地图转换为超级地图。

interface Converter<F>{

    fun convertFrom(map: F): SuperMap
    fun convertTo(map: SuperMap): F

}

这几种地图类型的所有者只需要实现地图类型超级地图

class MapAConverter: Converter<MapA> {

    override fun convertFrom(map: MapA): SuperMap {
        return SuperMap()
    }

    override fun convertTo(map: SuperMap): MapA {
        return MapA()
    }
}

/* more converters */

最后,我想到了一项服务,然后执行以下操作: 如果用户想要将 MapA 转换为 MapC,服务内部会转换 MapA -> SuperMap -> MapC,... 这样我就不必编码出所有可能的组合......

class ConverterService
{
    private val converters = mutableMapOf<KType, Converter<T>>()

    fun <T>register(converter: Converter<T>){
        this.converters[T::class] = converter
    }

    fun <F, T>Convert(map: F): T{

        // F ... from map
        val conv1 = converters[F::class]
        if (conv1 == null)
            throw Exception("No converter for this type of map")

        // convert to super class
        val sc = conv1.convertFrom(map)

        // T ... to map
        val conv2 = converters[T::class]
        if(conv2 == null){
            throw Exception("No converter for this type of map")
        }

        // convert to desirect class
        return conv2.convertFrom(sc) as T
    }
}

但这不起作用...

  1. 转换器 hashmap 不知道 T

  2. val conv1 = converters[F::class] 告诉我 F::class 需要重新定义并希望将 Convert 转换为内联函数。如果我这样做,它会变得更加复杂......

我的实现思路如下:

fun main() {

    // register some converters
    var cs = ConverterService()
    cs.register(MapAConverter())
    cs.register(MapBConverter())
    cs.register(MapCConverter())

    // input is map a
    val ma = MapA()

    // i want map c
    val mc = cs.Convert<MapA, MapC>(ma)

}

能以某种方式实现吗?我很高兴收到任何提示/建议。

谢谢!

【问题讨论】:

    标签: generics kotlin design-patterns type-conversion converters


    【解决方案1】:
    1. 使用mutableMapOf&lt;KClass&lt;*&gt;, Converter&lt;*&gt;&gt;()(意思是Converter with some unknown type parameter)。

    2. 如错误消息所述,您需要将FT 设为reified 才能使用F::class

      inline fun <reified F, reified T> Convert(map: F): T { ... }
      

      你也需要register。我不知道你为什么认为它“更复杂”。

    3. 您需要在Convert 内部进行一些细微的更改:将转换器转换为具有正确的类型参数而不是*,并在最后使用convertTo。我会做一个辅助函数

      private inline fun <reified T> converter(): Converter<T> {
          val result = converters[T::class]
          if (result == null) 
              throw Exception("No converter for ${T::class.qualifiedName}")
          else
              return result as Converter<T>
      }
      
      inline fun <reified F, reified T> Convert(map: F): T {
          // F ... from map
          val conv1 = converter<F>()
          // convert to super class
          val sc = conv1.convertFrom(map)
      
          // T ... to map
          val conv2 = converter<T>()
          // convert to desired class
          return conv2.convertTo(sc)
      }
      

    【讨论】:

    • 转换器映射和注册功能怎么样? T::class 不是 KType。
    • 已修复(没有像 Java 版本那样检查并假设 KClass 扩展 KType)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-09
    相关资源
    最近更新 更多