在Java中,如何创建一个具有私有构造函数的类,其超类也具有私有构造函数?

5
作为一个例子:
public class Foo {
    private Foo() {}
}

public class Bar extends Foo {
    private Bar() {}

    static public doSomething() {
    }
}

这是一个编译错误。一个类至少需要隐式调用其父类的默认构造函数,而在这种情况下,在 Foo 中并不可见。

我能否从 Bar 中调用 Object 的构造函数呢?


Foo(){} 是私有的而不是受保护的,这是否有原因? - Sven Lilienthal
1
@svelil:假设它是在第三方库中,或者在我控制范围之外,我想要进行子类化。 - Hans Sjunnesson
4个回答

10
您无法直接这样做。至少需要将Foo的构造函数设置为包私有,虽然我可能会将其设置为受保护的。(注:本帖中的评论提出了一个很好的观点)

如果两者都放在同一个包中,包私有就足够了。 - starblue
@starblue - 我相信这就是他说“至少”的原因。 - Ryan Thames
包比protected更加限制性,因此“至少”是错误的。如果两者都在同一个外部类中,则认为私有构造可访问。 - Tom Hawtin - tackline

7
这实际上是一种糟糕的继承方式(即实现继承)的症状。原始类可能没有被设计为可继承,因此选择使用私有构造函数,或者整个API设计不良。
解决方法不是想方设法继承,而是看看是否可以通过接口组合对象而非继承来实现。即,类Foo现在变成了接口Foo,有一个FooImpl。然后接口bar可以扩展Foo,有一个BarImpl,与FooImpl无关。
在BarImpl内部,如果希望进行代码重用,可以将FooImpl作为成员变量,但这完全取决于实现,并不会暴露出来。

2
只要Foo有一个私有构造函数,你就不能创建Bar的实例。唯一的方法是让Foo有一个受保护的构造函数。

2
如果一个超类有一个私有构造函数,那么子类甚至都无法编译。 - Rob Williams

1

在Bar作为Foo的子类时,你不能直接调用Object的构造函数,它必须通过Foo的构造函数来进行调用,而在这种情况下,Foo的构造函数是私有的。

当你将Foo的构造函数声明为私有时,它不会创建一个默认的公共构造函数。由于Bar必须调用Foo的构造函数,因此不可能将其保持为私有。我建议像其他人一样使用protected而不是private。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接