Task1813 and task1814 were beyond my capabilities at the moment and I downloaded the correct solutions.
Now I am learning from the ready solutions.:)
task1813 : it creates a custom OutputStream class by wrapping the FileOutputStream.
All the methods had to be overwritten, the calls are forwarded to the original=wrapped object.
Result: the custom stream works the same as a regular FileOutputStream, only with extra functionality added.
task1814: it ceates a custom InputStream class by NOT wrapping the FileInputStream.
It is solved by plain inheritance. Adds extra functionality in its constructor.
No method needed to be overwritten!
Result: works the same as a regular FileInputStream, only extra functionality is added.
The two tasks are solved differently, one uses wrapper technique, the other does not.
But the result seems to be the same: our own stream class works the same as the original Java one, with a little extra functionality.
My question:
Is one solution better than the other?
Is there any benefit to one, disadvantage to the other?
Is there any significant difference - that I don't notice?
What is the difference between wrapper and inheritance?
Resolved
Comments (4)
- Popular
- New
- Old
You must be signed in to leave a comment
Thomas
1 July 2021, 07:05solution
That's mostly design decisions. At this time you have learned that inheritance can be very powerful but it's not good to use it everywhere as it may make things complicated. You probably remember the rule of thumb that if two classes have a is-a relationship then inheritance is excellent two use. If they have a has-a relationship then better use composition. That's something you can use here as well.
Sometimes you can't use inheritance as your class already has a base class other than Object. Then you need to use delegation (or you try to get around of that with inner classes or interfaces).
Or the opposite, you want ot need to use inheritance cause you already have written code for the base class and want to reuse that. Then you have no choice.
But back to the is-a has-a relationships. The first copies all the methods of the base, tha latter the functionality. An example for you that I read somewhere:
Imagine the Stack class of the Java API. It has just a few methods mainly peek, pop and push. But Stack is obsolete as you now should use Deque (an interface). Deque defines Stack and Queue methods. A class that implements Deque is LinkedList and that one has in its ancestor list an AbstractList. So a lot of methods are gathered here (~ 40 or so, better would be to use ArrayDeque for the Stack fuctionality but LinkedList has more mothods so I use it as an example). Let's assume you want to create your own Stack implementation using LinkedList as Base. A Stack is no LinkedList but a Stack has some of the methods a LinkedList has. The rule of thumbs tells us to use composition (or here delegation). But what benefit do we have? When you use inheritance you copied all the methods of LinkedList to your new Stack class. You need to overwrite all off the methods and let them throw an exception if a user of your class uses a non Stack method.
If you use delegation you just code delegate to the methods you needs and that's here peek pop and push. Voila, all you wanted.
+2
Thomas
1 July 2021, 11:15
I forgot to say that delegation allows you to change behaviour at runtime (just send another wrapped object to the constructor or a switch method) while inheritance is static.
In the above example that'll be the mentioned ArrayDeque. I could use my Stack class to delegate to ArrayDeque instead to a LinkedList and I can switch between those two at runtime. If my Stack inherits from LinkedList then this is fix and can't be changed whilst running the program.
0
Gellert Varga
1 July 2021, 12:30
Thanks for the explanation!
I thought I understood completely when I read your first reply, but now I'm a bit confused by your latest post.:-D
1) I have a Collection hierarchy table, but it was missing this ArrayDeque. I have drawn it into. Did I put it in the right place? I need to be aware of the class structure to fully understand your example.
2) How can I send another type object to be wrapped?
If the private field and the constructor of the CustomStack class that stores/expects the original (the object to be wrapped) looks like this:
then i think it will definitely not be able to accept an ArrayDeque object to be wrapped.
Instead, should the code be written as follows?

0
Thomas
1 July 2021, 12:52
yes, you need compatible types like in your second example and that's done easily with an interface.
0