从Java代码构造Kotlin类的实例 主要+辅助构造函数工厂

问题描述

我有一个包含15个字段的Kotlin数据类。当我使用主要构造函数在Kotlin代码中构造此类的实例时,我可以利用一些有用的功能,例如:

  • 忽略具有认值的字段
  • 使用命名参数

但是,当从Java代码构造此Kotlin类的实例时,我面临这样一个事实,即我需要以正确的顺序在构造函数中提供所有15个参数,而无法命名它们。当此Java代码是单元测试时,这特别不方便,在这里我对填充所有这些字段并不真正感兴趣,而对测试仅有用一两个。

使用纯Java时,我不会遇到这个问题,因为我将使用(Lombok)构建器来构造对象的实例,并且可以灵活地仅提供我感兴趣的字段。

是否有减轻这种问题的方法,或者这是混合Java和Kotlin所要付出的代价?

解决方法

有没有办法减轻这个问题...

排序,但不是开箱即用的解决方案。详情请见下文。

...这是我混合Java和Kotlin所要付出的代价吗?

不,不是。如果我们解决这个问题,您会注意到Java无法提供默认值,因此与Kotlin一起使用时不方便。构造复杂对象是Builder Pattern存在的主要原因。但是Kotlin为我们提供了一种解决方案,可以避免大多数与构造复杂对象有关的问题,并使过时的构建器模式过时。

如何处理?

没有一种解决方案,而是多种解决方案。我将立即列出至少两个我想到的东西:

  1. 主要+辅助构造函数;
  2. 工厂。

主要+辅助构造函数

使用此选项,您可以创建包含以下内容的整个列表的主构造函数 您的类应包含的参数,并引入辅助构造器,该构造器仅接受必需的值或默认情况下无法设置的值

class Example(val param1: Any,val param2: Any? = null,val param3: Any? = null) {
    // In this situation we have to use different argument names
    // to make explicit use of primary constructor.
    // e.g. if we remove `param1 = ` or rename `requiredParam` to `param1`
    // we will get an error saying: "There's a cycle in the delegation calls chain" 
    constructor(requiredParam: Any) : this(param1 = requiredParam)
}

工厂

就工厂而言,一切看起来几乎相同。虽然,此解决方案在Java中会更加详细,但它消除了使用命名参数的必要性,并赋予了我们进行更多准备工作的自由对象初始化。 我们甚至可以使其异步(好像是网络调用一样)!

class Example(val param1: Any,val param3: Any? = null) {
    object Factory {
        fun from(param1: Any): Example {
            return Example(param1)
        }
    }
}

结论

没有“正确”的解决方案。我们可以选择自己喜欢的一个,也可以找出一个新的。

  1. 主要+辅助构造函数:
      从Java使用时,
    • (+)不再那么冗长;
    • (-)如果辅助构造函数发生变化,则必须更新Java代码;
    • (-)要求构造函数参数使用不同的名称。
  2. 工厂:
    • (+)提供更大的自由度:例如您可以在from函数中计算某些东西,并且与构造函数相比,它更具可读性;
    • (+)隐藏构造函数实现。您以后可以更改构造函数,而无需修改任何Java代码或工厂函数;
    • 从Java使用时,
    • (-)会更加冗长。