具有不可见构造函数的 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 实施可能是最好的实施。
我正在使用一个外部库,我在其中遇到了一个我想扩展的 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 实施可能是最好的实施。