为什么
java.io.OutputStream
没有建模为接口而不是抽象类?
接口可以证明是有用的,例如,我认为 jUnit 测试。
部分方法已经实施。这对于接口来说是不可能的。
close()
void flush()
void write(byte[] b)
void write(byte[] b, int off, int len)
已经使用默认实现来实现。
javadoc给出了提示:
需要定义 OutputStream 子类的应用程序必须始终提供至少一个写入一个字节输出的方法。
(即
void write(int b) throws IOException
)
如果你看一下它的实际代码,这个抽象基类的默认其他
write()
方法使用你需要实现的唯一方法。
此外,输出流可能不会链接到实际资源(例如
ByteArrayOutputStream
):因此,此类还具有 .close()
和 .flush()
的默认实现,它们不执行任何操作,并且仅需要由具有以下功能的流覆盖:他们背后的实际资源。
就测试目的而言,单元测试的唯一区别实际上是您需要
extends
而不是implements
,并且不要忘记重写您需要的方法。或者使用模拟库(例如mockito,或jmock,或...)。
事实上,java.io.OutputStream(与java.io.InputStream相同)使用了Decorator模式。与该问题相关,以下是来自(Head First Design Patterns第93页)的回复:
重点是装饰器具有相同的类型是至关重要的 作为他们要装饰的物体。所以这里我们使用 继承来实现类型匹配,但我们没有使用 继承以获得行为。
这就是为什么我们更喜欢继承(AbstracClass)而不是接口 (多态性)在这种情况下。但请注意,在大多数其他情况下, 原则是相反的:“优先考虑组合(界面)而不是 继承(抽象类)”。
它可能是一个抽象类,因为除了一个方法之外,它的所有方法都是具体的(实现的)...并且您可以在需要其他东西(用于测试)时将其子类化,或者您也可以在某些测试情况下模拟它。 ..
它被制作为抽象类,因此可以将其视为接口。
关于
OutputStream
与 interface
不同,该类为方法 write
提供了默认实现。