在私有对象中使用私有构造函数并使用方法实例化类有什么好处?

时间:2019-02-13 20:52:55

标签: kotlin

我碰到了这段代码,我不确定为什么有人会这样做。基本上,作者决定将类构造函数设为私有,以便无法在文件外部对其进行实例化,并向该类中的同伴对象添加了一个公共方法,以创建该类的新实例。这种方法有什么好处?

这是我发现的:

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..
}

4 个答案:

答案 0 :(得分:2)

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

  • 在调用委托人之前,它可以做很多处理。 (如果超类构造函数使用需要计算的参数,这可能很重要。)

  • 它可以返回缓存的值,而不是适当的新实例。

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

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

  • 它使更改类的实现变得更容易,而又不影响其公共接口。

它也有一个重要的缺点:

  • 子类构造函数不能使用它。

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

有关更多信息,请参见this article,其中介绍了 Effective Java 中的建议以及该建议如何应用于Kotlin。

答案 1 :(得分:1)

如果将来您想将Foo更改为接口,则基于该方法的代码将继续起作用,因为您可以返回仍实现Foo的具体类,这与构造函数不同。已经存在了。

答案 2 :(得分:0)

一个特定于android的示例是,Fragments应该使用空构造来构造,并且您想要传递给它们的任何数据都应该放在一个包中。

我们可以创建一个static / companion函数,该函数接受该片段所需的参数,此方法将使用空的构造函数构造该片段,并使用包传递数据。

答案 3 :(得分:0)

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

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()

注意:您应该使用通用类型,而不要使用Any