界面可见性限制,但运行良好
Interface visibility restriction, but runs fine
在设计流体 API 时,有时我想使用接口 return 类型,以便调用者可以轻松地遵循可用的方法,或者如果他不这样做,则会出现编译器错误(Step Builder pattern 是一个例子)。
但是当我想使用接口只是为了指向下一个可用的方法时,比如:
package packageone;
public class SomeClass implements CanPrint {
private SomeClass() {
}
public static CanPrint get() {
return new SomeClass();
}
@Override
public void print() {
System.out.println("Runs fine!");
}
}
public interface CanPrint {//Compile error: must be defined in own file
public void print();
}
但是,启动快速测试工作正常(以下代码打印 "Runs fine!"):
package packagetwo;
import packageone.CanPrint;
import packageone.SomeClass;
public class Main {
public static void main(String[] args) {
CanPrint returnType = SomeClass.get();
returnType.print();
}
}
编译器可以'fooled'通过包装整个class:
package packageone;
public class Wrapper {
public static CanPrint get() {
return SomeClass.get();
}
public static class SomeClass implements CanPrint {
public static CanPrint get() {
return new SomeClass();
}
private SomeClass() {
}
@Override
public void print() {
System.out.println("Runs fine!");
}
}
public interface CanPrint {
public void print();
}
}
所以目前,当我想将接口与打算使用它的唯一代码保持在同一个位置时(因为调用者只需要该方法),我将它包装在一个包装器 class 中仅指向内部 class.
中的相同方法
为什么会有这个限制?另一个 class 可以导入接口,使用它,如果他们愿意的话,甚至可以实现他们自己的版本。所有这些似乎 运行 都没有问题。然而它没有编译。
注意:我已经尽可能地简化了我的例子,但正因为如此,人们可能不太清楚为什么会选择这种设计。
Why is this restriction in place?
它使编译器和人类更容易找到包含顶级 class 的源文件。
您可以通过以下方式公开接口:
- 将界面放在单独的文件中,如
ISomeClassCanPrint
。
- 或者将接口嵌套在class即returns的一个实例中。您的包装器接近于这种方法。
这是嵌套接口的另一个示例:
public static class SomeClassFactory {
public interface CanPrint {
public void print();
}
public static CanPrint get() {
return new SomeClass();
}
public static class SomeClass implements CanPrint {
@Override
public void print() {
System.out.println("Runs fine!");
}
}
}
更多详情
Java Language Specification, section 7.6: Top level type declarations涵盖了限制:
If and only if packages are stored in a file system (§7.2), the host system may choose to enforce the restriction that it is a compile-time error if a type is not found in a file under a name composed of the type name plus an extension (such as .java or .jav) if either of the following is true:
The type is referred to by code in other compilation units of the package in which the type is declared.
The type is declared public (and therefore is potentially accessible from code in other packages).
This restriction implies that there must be at most one such type per compilation unit. This restriction makes it easy for a Java compiler to find a named class within a package. In practice, many programmers choose to put each class or interface type in its own compilation unit, whether or not it is public or is referred to by code in other compilation units.
因此,虽然您可以在单个文件中声明多个 顶级 class,但最多可以公开一个以供文件外部访问。
但是,您可以根据需要公开任意数量的嵌套 class。
在设计流体 API 时,有时我想使用接口 return 类型,以便调用者可以轻松地遵循可用的方法,或者如果他不这样做,则会出现编译器错误(Step Builder pattern 是一个例子)。
但是当我想使用接口只是为了指向下一个可用的方法时,比如:
package packageone;
public class SomeClass implements CanPrint {
private SomeClass() {
}
public static CanPrint get() {
return new SomeClass();
}
@Override
public void print() {
System.out.println("Runs fine!");
}
}
public interface CanPrint {//Compile error: must be defined in own file
public void print();
}
但是,启动快速测试工作正常(以下代码打印 "Runs fine!"):
package packagetwo;
import packageone.CanPrint;
import packageone.SomeClass;
public class Main {
public static void main(String[] args) {
CanPrint returnType = SomeClass.get();
returnType.print();
}
}
编译器可以'fooled'通过包装整个class:
package packageone;
public class Wrapper {
public static CanPrint get() {
return SomeClass.get();
}
public static class SomeClass implements CanPrint {
public static CanPrint get() {
return new SomeClass();
}
private SomeClass() {
}
@Override
public void print() {
System.out.println("Runs fine!");
}
}
public interface CanPrint {
public void print();
}
}
所以目前,当我想将接口与打算使用它的唯一代码保持在同一个位置时(因为调用者只需要该方法),我将它包装在一个包装器 class 中仅指向内部 class.
中的相同方法为什么会有这个限制?另一个 class 可以导入接口,使用它,如果他们愿意的话,甚至可以实现他们自己的版本。所有这些似乎 运行 都没有问题。然而它没有编译。
注意:我已经尽可能地简化了我的例子,但正因为如此,人们可能不太清楚为什么会选择这种设计。
Why is this restriction in place?
它使编译器和人类更容易找到包含顶级 class 的源文件。
您可以通过以下方式公开接口:
- 将界面放在单独的文件中,如
ISomeClassCanPrint
。 - 或者将接口嵌套在class即returns的一个实例中。您的包装器接近于这种方法。
这是嵌套接口的另一个示例:
public static class SomeClassFactory {
public interface CanPrint {
public void print();
}
public static CanPrint get() {
return new SomeClass();
}
public static class SomeClass implements CanPrint {
@Override
public void print() {
System.out.println("Runs fine!");
}
}
}
更多详情
Java Language Specification, section 7.6: Top level type declarations涵盖了限制:
If and only if packages are stored in a file system (§7.2), the host system may choose to enforce the restriction that it is a compile-time error if a type is not found in a file under a name composed of the type name plus an extension (such as .java or .jav) if either of the following is true:
The type is referred to by code in other compilation units of the package in which the type is declared.
The type is declared public (and therefore is potentially accessible from code in other packages).
This restriction implies that there must be at most one such type per compilation unit. This restriction makes it easy for a Java compiler to find a named class within a package. In practice, many programmers choose to put each class or interface type in its own compilation unit, whether or not it is public or is referred to by code in other compilation units.
因此,虽然您可以在单个文件中声明多个 顶级 class,但最多可以公开一个以供文件外部访问。
但是,您可以根据需要公开任意数量的嵌套 class。