具有不可见构造函数的 public class 可以在另一个包中由 class 扩展吗?

Can a public class with invisible constructor be extended by a class in another package?

我正在使用一个外部库,我在其中遇到了一个我想扩展的 public class。它只是构造函数是包私有的,因此对我来说是不可见的。

public class Token implements IToken {
    Token(int kind, Object source, int offset, int endOffset) {
        ...
    }
    ...
}

我的子class会是

public class MyToken extends Token {
    ...
}

出现错误:

Implicit super constructor Token() is undefined for default constructor. Must define an explicit constructor

当我添加构造函数时:

MyToken(int kind, Object source, int offset, int endOffset) {
    super(kind, source, offset, endOffset);
}

我收到错误消息

The constructor Token(int, Object, int, int) is not visible

有什么方法可以扩展这个 class?如果不是,声明它的目的是什么public?

Token class.

不改变是不可能的

有些图书馆可以在 运行 时间内修改 class,但我强烈建议您不要这样做。

任何子class 需要能够访问至少一个基础class 的构造函数。

如果你想让子class存在于另一个包中,你必须至少使构造函数protected

由于这来自第三方库,他们似乎不希望您子class Token。对于您在这里需要做的任何事情,subclassing 都可能有替代方法。

不提供 public 构造函数是您(库作者)需要控制实例创建方式(例如实现单例或强制使用工厂方法)时的常见模式。

If not, what is the purpose of declaring it public?

A public class 可以从任何地方使用,也就是说,你可以在给定的实例上调用方法(即使你不能新实例自己)。

您可以使用令牌,但不能创建它们。例如,这种结构意味着您可能会在程序中使用类似下面的内容:

List<Token> tokens = stream.getTokens();

基本上库会创建令牌,您可以使用它们但不能扩展或创建您自己的令牌。

关于使用 protected 构造函数制作 class public 你的观点是有效的,但你可以尝试组合来实现所需的功能,其中 MyToken class 包含引用Token class 个。这样,我们也将遵循 Composition over Inheritance 原则。

public class 的目的是将构造函数留给朋友 class,或者静态工厂(创建)方法。

这里可能就是这种工厂模式。然后你可以使用:

public class MyToken implements IToken {
    private Token delegate;

    public MyToken(int kind, Object source, int offset, int endOffset) {
        // Factory usage:
        delegate = Token.create().withKind(kind).withSource(source)...;
    }

    public int getKind() {
        return delegate.getKind();
    }

    ...

否则,您可以在 中创建与 Token 相同的程序包 public 构造函数的(基础)class。 模块化 java > 8 将不再允许此技巧。

我个人猜测 Token 将由同一个包中的某些 Parser/Scanner class 创建。实际上,甚至可能会返回 Token 的子 class,因为它可以是嵌套的内部 class,可以访问 Parser 容器的字段,例如 line as String,filePath.

创建您自己的 IToken 实施可能是最好的实施。