Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Kotlin 拥有一个私有构造函数和一个在伴随对象中使用方法来实例化一个类有什么好处?_Kotlin - Fatal编程技术网

Kotlin 拥有一个私有构造函数和一个在伴随对象中使用方法来实例化一个类有什么好处?

Kotlin 拥有一个私有构造函数和一个在伴随对象中使用方法来实例化一个类有什么好处?,kotlin,Kotlin,我碰到了这个代码,我不知道为什么会有人这样做。基本上,作者决定将类构造函数设置为私有的,这样就不能在文件之外实例化它,并向类中的伴生对象添加了一个公共方法,该对象创建了该类的新实例。这种方法的好处是什么 这就是我发现的: class Foo private constructor(private val arg1: Any) { //more code here.. companion object { fun newFoo(arg1: Any) = Foo(ar

我碰到了这个代码,我不知道为什么会有人这样做。基本上,作者决定将类构造函数设置为私有的,这样就不能在文件之外实例化它,并向类中的伴生对象添加了一个公共方法,该对象创建了该类的新实例。这种方法的好处是什么

这就是我发现的:

class Foo private constructor(private val arg1: Any) {
    //more code here..
    companion object {
        fun newFoo(arg1: Any) = Foo(arg1 = arg1)
    }
}
为什么比这个好

class Foo(private val arg1: Any) {
    //more code here..
}

如果您希望将来将
Foo
更改为一个接口,那么基于该方法的代码将继续工作,因为您可以返回一个仍然实现
Foo
的具体类,这与不再存在的构造函数不同。

android特有的一个示例是,这些片段应该用一个空的构造函数来构造,您希望传递给它们的任何数据都应该放在一个包中


我们可以创建一个静态/伴随函数,它接受我们需要的片段参数,这个方法将使用空构造函数构造片段,并使用bundle传递数据

有许多有用的案例,例如Kiskae所描述的。另一个好方法是能够“给出构造函数的名称”:


注意:您应该使用泛型类型而不是
Any

提供工厂方法而不是公共构造函数有几个好处,包括:

  • 它可以在调用构造函数之前进行大量处理。(如果超类构造函数采用需要计算的参数,这一点很重要。)

  • 在适当的情况下,它可以返回缓存的值,而不是新实例

  • 它可以返回一个子类。(这允许您将顶级类作为接口,如另一个答案中所述。)确切的类可以在调用之间有所不同,甚至可以是匿名类型

  • 它可以有一个名称(如另一个答案中所述)。如果需要使用相同参数的多个方法,这一点尤其重要。(例如,可以由矩形坐标或极坐标构成的点对象。)但是,工厂方法不需要特定名称;如果在伴生对象中实现
    invoke()
    方法,则可以使用与构造函数完全相同的方式调用它

  • 这样可以更容易地更改类的实现,而不会影响其公共接口

它还有一个重要的缺点:

  • 子类构造函数不能使用它
工厂方法在Kotlin中的使用似乎比Java少,这可能是因为Kotlin对于主构造函数和属性的语法更简单。但它们仍然值得考虑——特别是当Kotlin伴生对象可以继承时


有关更深入的信息,请参见,其中介绍了中的建议以及如何将其应用于Kotlin。

一般来说,它允许您在以后更改实现,无论是更改为新的子类型,还是以后重新构造类的构造函数,或者其他什么。它还允许您定义一个更详细的名称,用于以这种方式构造对象,这比类型的名称更详细。例如,对于那些想深入挖掘的读者:@FrankNeblung是一个很好的参考资料——而且比我自己记忆不清的想法要权威得多!我会加进去的,谢谢。
class Foo<S: Any, T: Any> private constructor(private val a: S, private val b: T) {
    //more code here...
    companion object {
        fun <S: Any> createForPurposeX(a: S) = Foo(a = a, b = "Default value")
        fun createForPurposeY() = Foo(a = 1, b = 2)
    }
}
Foo.createForPurposeX("Hey")
Foo.createForPurposeY()