Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shouldn't ObjectInputStream extend FilterInputStream?

The block quotes are from the Java Docs -

A FilterInputStream contains some other input stream, which it uses as its basic source of data, possibly transforming the data along the way or providing additional functionality.

A DataInputStream lets an application read primitive Java data types from an underlying input stream in a machine-independent way.

The DataInputStream therefore extends FilterInputStream

An ObjectInputStream deserializes primitive data and objects previously written using an ObjectOutputStream.

However, for some reason the ObjectInputStream does NOT extend FilterInputStream even though it is also reading objects (this time and not primitive types) from the underlying input stream. Here is the branching of the concerned classes.

alt text

Is there is a design reasoning for the same?

like image 676
Vaibhav Bajpai Avatar asked May 24 '10 12:05

Vaibhav Bajpai


2 Answers

Sensible question. Thinking of it, I believe that Object*Stream could have been designed to extend Filter*Stream (the same applies to Output or Input). Why it wasn't done so? Perhaps because:

  1. It gives no real benefit. As explained by Maciej, the point of Filter*Stream, apart from some unimportant organization of classes, is to provide some common default (and rather trivial) implementation of those classes that have that pattern (read/write from some underlying stream, eventually transforming the stream), to be extended by other classes (from Java API or user). But Filter*Stream is not about interfaces : you'll almost never find or implement some method that requires a Filter*Stream as argument, for example. Hence, the decision of making a class inherit *Stream or Filter*Stream, when there is the alternative, is mostly an implementation decision; the users of the class will basically not care.

  2. The designers of ObjectOutputStream decided to give extra flexibility to those willing to extend the class, totally reimplementing it, by giving an extra empty constructor (with no underlying OuputStream). This feature (rather rare, I think) puts the class (conceptually and implementation wise) a litte far apart the Filter*Stream class. Again, this does not seem conclusive.

like image 199
leonbloy Avatar answered Oct 13 '22 00:10

leonbloy


There is distinction between:

  • Logical inheritance (shares interface)
  • 'Code' inheritance when you share the code between classes

Logically LinkedList is not AbstractList as it is not abstract. However from the code point of view it is benefitial to share some implementation of List methods as they can be implement in terms of others, usually with the same efficiency (for example isEmpty can be implemented as size() == 0).

Some platforms, such as GObject (or to some extend Haskell - although it is not OO language and many things are totally different) alows default implementation of methods in interface which is defining it.

However it is not the case with Java which uses Abstract* classes to reuse the code. Filter*Stream is not so much defining that the output is sent somewhere (as the whole point of the Java I/O is that the produer/reciver does not care) but it is used to reuse common code.

like image 25
Maciej Piechotka Avatar answered Oct 13 '22 00:10

Maciej Piechotka