Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/316.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
Java 具有不可见构造函数的公共类能否由另一个包中的类扩展?_Java_Java 8_Eclipse Cdt - Fatal编程技术网

Java 具有不可见构造函数的公共类能否由另一个包中的类扩展?

Java 具有不可见构造函数的公共类能否由另一个包中的类扩展?,java,java-8,eclipse-cdt,Java,Java 8,Eclipse Cdt,我正在使用一个外部库,在这里我遇到了一个我想要扩展的公共类。它唯一的构造函数是包私有的,所以我看不见 public class Token implements IToken { Token(int kind, Object source, int offset, int endOffset) { ... } ... } 我的子类是 public class MyToken extends Token { ... } 这将获得一个错误: 默认构

我正在使用一个外部库,在这里我遇到了一个我想要扩展的公共类。它唯一的构造函数是包私有的,所以我看不见

public class Token implements IToken {
    Token(int kind, Object source, int offset, int endOffset) {
        ...
    }
    ...
}
我的子类是

public class MyToken extends Token {
    ...
}
这将获得一个错误:

默认构造函数的隐式超级构造函数标记()未定义。必须定义显式构造函数

当我添加构造函数时:

MyToken(int kind, Object source, int offset, int endOffset) {
    super(kind, source, offset, endOffset);
}
我收到了错误信息

构造函数标记(int,Object,int,int)不可见


有没有办法扩展这个类?如果不是,那么宣布它公开的目的是什么?

。不更改
标记
类是不可能的


有些库可以在运行时修改类,但我强烈建议您不要这样做。

任何子类都必须能够访问基类的至少一个构造函数

如果希望子类位于另一个包中,则必须使构造函数至少受到保护

因为它来自第三方库,所以看起来他们不希望您将
令牌子类化。对于您在这里需要做的任何事情,可能都有一种替代子类化的方法

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

如果没有,宣布它公开的目的是什么


公共类可以在任何地方使用,也就是说,您可以对给定的实例调用方法(即使您自己无法创建新实例)。

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

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

因此,基本上,库将创建令牌,您可以使用它们,但不能扩展或创建自己的任何类。

您的观点在使用
受保护的
构造函数将类
公开方面是有效的,但您可以尝试组合以实现所需的功能,其中
MyToken
类包含
Token
类的引用。这样,我们也将遵循继承之上的组合原则。

具有受限构造函数的公共类的目的可以是将构造留给友元类或静态工厂(创建)方法

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

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
构造函数的(基类)使用模块化java>8将不再允许使用此技巧。

我个人猜测,
标记
将由同一个包中的某个
解析器
/
扫描仪
类创建。实际上,甚至令牌的子类也可能被返回,因为它可以是一个嵌套的内部类,可以访问解析器容器的字段,比如
line
as String、
filePath


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

如果不是,那么将其声明为公共的目的是什么它是一个具体的类,因此声明它为公共的目的是可以从其他包中使用它。你不能扩展它,但你仍然可以从中创建对象。谁说他不能创建它们?@Stultuske:如果你没有可见的构造函数,你就不能创建实例。您只能从其他有权访问内部构造函数的库方法中获取它们。@Stultuske:包私有构造函数说…:-)如果您建议使用工厂,那么它仍然是创建常规令牌类的工厂,可能没有提供OP所需的功能。他可能能够创建实例。那里可能有个工厂somewhere@Stultuske:是的,您可以调用工厂为您创建实例。但是您不能直接这样做,而且工厂(也是由库提供的)可以控制这种情况的确切发生方式(例如防止无效状态)。但是我不喜欢扫描器创建这些令牌的方式。我们需要看到更多的代码以及如何使用
MyToken
,但可能最好不要子类化。通常,最好让解析器构造它的AST/随便什么,然后在上面工作(而不是将任何额外的业务逻辑混合到解析器创建的令牌中)。@Sadik:为什么您不喜欢扫描仪创建令牌的方式(这确实是个问题)?@Thilo对于我的应用程序,令牌的创建不正确。例如,我需要解析器处理一个标记“@func”,但扫描程序创建了两个标记“@”和“func”。我想我可以用我想要的方式使用扫描器创建标记,或者在标记化之后但在解析之前需要一个后处理步骤。@Sadik我明白了。是的,你需要一个不同的扫描仪,或者一些后期处理。如果无法将扫描仪配置为符合您的需要,则最好另找一台。也许可以打开另一个关于这个特定库的特定解析问题的问题。有更多领域知识的人可能会插话。