Java OutputStream作为接口
为什么Java OutputStream作为接口,java,interface,io,Java,Interface,Io,为什么java.io.OutputStream没有建模为接口而不是抽象类 我认为,接口可以被证明是有用的,例如单元测试。它是作为抽象类创建的,因此可以将其视为接口 关于OutputStream与接口不同,该类为方法write提供默认实现,其中一些方法已经实现。这对于接口是不可能的 close() void flush() void write(byte[] b) void write(byte[] b, int off, int len) 已使用默认实现实现。javadoc给出了一个提
java.io.OutputStream
没有建模为接口而不是抽象类
我认为,接口可以被证明是有用的,例如单元测试。它是作为抽象类创建的,因此可以将其视为接口
关于
OutputStream
与接口不同,该类为方法write
提供默认实现,其中一些方法已经实现。这对于接口是不可能的
close()
void flush()
void write(byte[] b)
void write(byte[] b, int off, int len)
已使用默认实现实现。javadoc给出了一个提示:
需要定义OutputStream子类的应用程序必须始终提供至少一个写入一个字节输出的方法
(也就是说,voidwrite(intb)抛出IOException
)
如果查看它的实际代码,这个基本抽象类的默认其他write()
方法将使用您需要实现的唯一方法
此外,输出流可能不会链接到实际资源(例如,ByteArrayOutputStream
):因此,此类还具有.close()
和.flush()
的默认实现,这些实现不做任何事情,只需要由后面有实际资源的流覆盖
至于测试目的,单元测试的唯一区别实际上是您需要扩展
,而不是实现
,并且不要忘记覆盖您需要的方法。或者使用模拟库(如mockito、jmock或…。它可能是一个抽象类,因为它的所有方法都是具体的(实现的)。。。您可以在需要其他东西(用于测试)时将其子类化,或者在某些测试情况下也可以对其进行模拟…事实上,java.io.OutputStream(与java.io.InputStream相同)使用。关于这个问题,以下是(第93页)的回复:
关键是装饰器必须具有相同的类型
作为他们要装饰的对象。所以我们在这里使用
继承来实现类型匹配,但我们不使用
继承以获取行为
这就是为什么我们更喜欢继承(类)而不是接口
(多面体)在这种情况下。但请注意,在大多数其他情况下,
原则是相反的:“偏爱成分(界面)而不是
继承(抽象类)”
好吧,您可以使用模拟库进行单元测试Mockito确实提供了一种测试抽象类的方法,即spy。但是spy(s)要求您提供一个具体的实现,这个实现不被认为是干净的。。。无论如何,对于你的问题来说,这有点离题;)我想纠正我自己。jmock似乎提供了一些扩展(ClassImposteriser)来正确模拟抽象类。拥有抽象类而不是接口有什么好处?#抽象类的好处:有些方法已经可以实现了。缺点:您不能扩展多个类,但可以实现多个接口。@GangnamStyleOverflower错误:在Java 8(尚未最终版本)之前,您不能在接口中实现方法,因此优点是您可以实现(其中的一些)方法。@GangnamStyleOverflower错误:我是这么说的:@MrSmith42您可以始终拥有一个实现接口的抽象类。他们可以轻松地创建接口和抽象类class@Steve郭:通常两者兼得会很好,但可悲的是,孙经常决定不这样做-(是的,看起来是这样。他们忽略了当时可能不相关的设计选择?也可以使用接口实现类型匹配?请参阅Decorator pattern的Wikipedia页面中的Java示例以获取一些插图。是的,但我们需要的是一个框架实现。在某些情况下,接口不允许有方法实现在某些情况下,我们需要一个抽象的框架实现类。这也是Java集合框架背后的想法(正如Joshua Bloch在他的著作《有效Java,第18项:首选接口而非抽象类》中所解释的那样)。争论的焦点是为什么不在AbstractInputStreamBase(框架实现)的基础上再加上一个InputStream接口。(集合是界面驱动设计的一个很好的例子。)虽然,Java可以通过InputStream交互和AbstractInputStreamBase实现同样的效果。Jmock确实提供了足够的扩展来模拟与模拟接口一致的抽象类。感谢指针。是的,当然,但它真的值得吗?接口都很好,但滥用它们会导致代码更复杂比其他情况下更复杂。可能是口味的问题!到目前为止,我可以得出的结论是,当前的InputStream现在是我们必须处理的遗留类。它从1996年发布的Jdk 1.0开始就存在了。不确定当时的主流单元测试实践如何。