kotlin,如何简化向基类构造函数传递参数?

inn*_*ov8 6 constructor base-class kotlin

我们有一个包,我们希望将其从 python 转换为 kotlin,以便能够使用该包迁移系统。

在包中有一组类,它们都是公共基类的变体或“风味”。

大多数代码都在基类中,它具有大量可选参数。所以考虑:

open class BaseTree(val height:Int=10,val roots:Boolean=true, //......还有很多!!

class FruitTree(val fruitSize, height:Int=10, roots:Boolean=true,
  //  now need all possible parameters for any possible instance
   ):BaseTree(height=height, roots=roots //... yet another variation of same list
Run Code Online (Sandbox Code Playgroud)

代码实际上并不是树,我只是认为这是传达想法的一种简单方式。基类有大约 20 个参数,大约有 10 个子类,每个子类实际上需要重复来自基类的参数列表的相同两个变体。如果参数列表发生变化,那真是一场噩梦!

那些来自 Java 背景的人可能会评论“20 个参数太多了”,可能会错过这是可选参数,影响这方面设计的语言特性。20个必需参数会很疯狂,但10个甚至20个可选参数并不少见,例如查看sqlalchemy表

在python中,你可以调用一个基类构造函数:

def __init__(self, special, *args, **kwargs):
   super().__init(*args, **kwargs)  # pass all parameters except special to base constructor
Run Code Online (Sandbox Code Playgroud)

有没有人知道一种技术,使用不同的方法(也许使用接口或其他方法?)来避免为每个子类一遍又一遍地重复这个参数列表?

inn*_*ov8 5

没有设计模式可以简化此用例。

最佳解决方案:重构代码以使用更像 Java 的方法:使用属性代替可选参数。

用例解释:具有大量可选参数的广泛使用的类或方法在 Java 中根本不切实际,而 kotlin 的发展最成熟的方式是使 java 代码变得更好。一个有 5 个可选参数的 Python 类,翻译成没有可选参数的 Java 类,可能有 5 个!(5的阶乘是60)不同的Java签名......换句话说,一团糟。

显然,任何对象都不应该经常使用巨大的参数列表进行实例化,因此正常的Python类仅在大多数调用不需要指定这些可选参数时演化为类,并且可选参数用于异常情况。这里的实际用例是大量可选参数的实现,其中使用超过 3 个可选参数来实例化任何单个对象的情况应该很少见。因此,一个具有 10 个可选参数的类在应用程序中使用了 500 次,仍然期望其中 3 个可选参数是一个实例中曾经使用过的最大参数。但这只是一种在 Java 中行不通的设计方法,无论该类被重用多少次。

在 Java 中,函数确实有可选参数,这意味着在 Java 库中以这种方式实例化对象的情况永远不会发生。

考虑一个具有一个强制实例参数和五个可能选项的对象。在 Java 中,这些选项每个都是能够由 setter 设置的属性,然后实例化对象,并且 setter 调用设置任何相关选项,但很少需要更改该选项的默认值。

缺点是这些选项无法从构造函数中设置并保持不可变,但生成的代码减少了可选参数。

另一种方法是拥有一组不那么“瑞士军刀”的对象,用一组专用工具代替一个万能工具,即使代码可以被视为同一主题的细微差别。

尽管 kotlin 支持可选参数,但 kotlin 中的继承结构尚未针对此功能的大量使用进行优化。