这篇博客文章旨在解释当我们期望对象实现不同的接口时如何在Java中使用交集类型。
Interface Segregation Principle
接口隔离原则(ISP)规定接口应包含尽可能少的方法。 换句话说,接口的客户端应使用此接口的所有方法。
例如,让我们来文件接口:
interface File {
Collection<String> readLines();
void write(String line);
void deleteFile();
}
class LocalFile implements File {
// ...
}
作为此接口的客户端,我极不可能需要所有方法。 我可能只想读取文件,在这种情况下,我当然不想删除它。 如果我只想删除文件,则可能不想读取其所有行。
为了避免这种情况,最好将此接口分为3个单独的接口:
interface FileReader {
Collection<String> readLines();
}
interface FileWriter {
void write(String line);
}
interface FileDestroyer {
void deleteFile();
}
class LocalFile implements FileReader, FileWriter, FileDestroyer {
// The concrete class can implement all 3 interfaces
// ...
}
现在,客户端可以只需要其所需的接口,而忽略其余接口。
Interface Combination
编写微型接口可以很好地执行ISP并降低代码的耦合。 但是,当客户端要读取文件时会发生什么和同时写?
前两个代码段无法编译,因为其中一个接口未实现:
void readAndWrite(FileReader reader) {
reader.readLines();
reader.write("Hello"); // That won't compile since reader does not implement FileWriter
}
void readAndWrite(FileWriter writer) {
reader.readLines(); // That won't compile since writer does not implement FileReader
reader.write("Hello");
}
作为替代方案,可以传递一个实例本地文件但它在方法和本地文件具体的类,完全破坏了接口的全部目的。
void readAndWrite(LocalFile file) {
file.readLines();
file.write("Hello");
// That will compile but it is not recommended
}
自从Java 1.5和泛型的引入以来,一种称为Intersection Types的功能允许在这种情况下组合接口。
Intersection Types to the Rescue
以下代码使用交集类型来解决需要一个实现多个接口的对象的问题:
<T extends FileReader & FileWriter> void readAndWrite(T file) {
file.readLines();
file.write("Hello");
}
的和amp;符号表示该方法需要一个类型Ť既实现了文件阅读器和FileWriter接口。
Conclusion
交集类型是Java中未广泛使用的功能。 但是,它非常强大,因为它允许编写非常小的接口并按需组合它们。 从现在开始,没有任何借口来编写具有数十种完全不相关的方法的大型胖接口!