aspose file tools*
The moose likes Java in General and the fly likes Inheritance / Komposition of multiple abstract classes Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Java in General
Bookmark "Inheritance / Komposition of multiple abstract classes" Watch "Inheritance / Komposition of multiple abstract classes" New topic
Author

Inheritance / Komposition of multiple abstract classes

Christian Heupel
Greenhorn

Joined: Mar 15, 2012
Posts: 4
Hi together

first of all: I have already found a lot of help in this forum the last time and just want to say its awesome what you guys are doing here! Hope i will find time and muse to contribute a bit myself

Now i have a problem for which i was not able to find a solution so far and hope one of you might give me some nice idea on how to work something out:

I am currently working in a project where I need to consume a specific set of webservices. Basically these services can be categorized as webservices that 1) retrieve data 2) push data and 3) do both. All these webservices obey certain workflows which I want to capture in an abstract class that looks something like this:


Building on this, I have two sub-classes that implement some functionality to receive data, validate return codes. For receiving information, I also need to convert the data i get from the webservice to data that makes sense to the domain my code is placed in. These classes look somewhat like that:



And:


On this basis, I can pretty much implement quiet a nice range of providers, and really only focus on the individual parts of each webservice (and what needs to be done around that stuff...). Now my problem is: How do i write a provider which must be able to do both send and receive data on the same webservice?

In other words: How do I reuse the already implemented functionality of two abstract classes? If these classes weren't abstract, I would simply have some interface providing all the functionality and use composition + delegation to create an abstract class, since these classes are already abstract, i cannot simply create private members (I could but then i would have to implement their abstract functions which i would love to omit..).

Does anyone have some kind of suggestion? (Maybe I'm doing something wrong in my design from the beginning, but i cannot really find a good way to do it differently).

Thanks a lot in advance!
Jeff Verdegan
Bartender

Joined: Jan 03, 2004
Posts: 6109
    
    6

I didn't read all that code, but if you want one class to implement two services, then composition is probably a good bet.



You mention something about how you can't use composition because you only have abstract classes. I'm not really sure what you're saying there, and it doesn't make sense. If you want a Sender, then you need a concrete implementation of Sender. If you have an abstract Sender class, then you need to finish the implementation. And in particular, if you want to use composition like this, then you need to create a concrete Sender and a concrete Receiver.

On the other hand, if you don't already have or can't easily create these concrete classes, then maybe you don't gain much by composition. The benefit of composition is that you get to use an existing class's implementation without coupling yourself to it as a subclass. So maybe you just want to implement those methods directly in SR and skip the composition.

Finally, and I think this may be what you're really getting at, if there's a lot of code in an abstract Sender and a lot of code in an abstract Receiver, and you're saying you want to use both of those codebases but can't because you can't extend two classes, then we're back to what I first said: Create concrete subclasses of those two, and delegate to them, as in my example.
Christian Heupel
Greenhorn

Joined: Mar 15, 2012
Posts: 4
Hi and thanks for your quick reply.

First of all: My problem is not the "getting it to work". It's the "making it as good as possible" part that's bugging me. Well there is a lot that I might have not pointed out as I should have and you might have seen in the code, so let met point out the issues here:

The main issue I'm having with this is that both the "sender" and "receiver" inherit from the same (abstract) parent. When I want to use composition for a class that represents "both functionalities", I am forced to create redundant code. As an Example:



If you want to use composition to create a "MultipicationAndDivisionCalculator", you will have to implement "add" and "subtract" two times, one of which will never be used. Instead I want it to stay abstract (maybe this is still not the "final class" and should stay concrete..). The Generics used in that whole stuff also keep me from liking this solution as I need to specify the generic types in the very moment I instantiate the classes and lose their power for children of this "coupled" class (I would have to create a concrete MultiplicationAndDivisionCalculator) for every possible Combination of each generic type in worst case (sorry for mixing up the generics from the former example into this little example here ). Also I don't really want to create the "MultiplicationAndDivisionCalculator" and create the other Calculators as Facades of it since this would limit my possibilities as well (and again the generics would make it just ugly..).

Do you now feel like my problem might be a bit more understandable?

Best,
Chris
Jeff Verdegan
Bartender

Joined: Jan 03, 2004
Posts: 6109
    
    6

Christian Heupel wrote:
The main issue I'm having with this is that both the "sender" and "receiver" inherit from the same (abstract) parent. When I want to use composition for a class that represents "both functionalities", I am forced to create redundant code. As an Example:



If you want to use composition to create a "MultipicationAndDivisionCalculator", you will have to implement "add" and "subtract" two times, one of which will never be used.


My first choice would be to redesign the type hierarchy so that this didn't happen in the first case. Assuming you can't do that, the next best thing would be a less extreme rearrangement. For MultCalc's and DivCalc's implementations of Calculator, rather than have them implement the methods directly, they could delegate to a simple concrete Calculator implementation. If you have them accept that object as a c'tor parameter, then when the MulDivCalc class delegates to them, it can pass them both the same Calculator. This way there's no dead object, and the only repeated code is the calls to the Calculator delegate.



Christian Heupel
Greenhorn

Joined: Mar 15, 2012
Posts: 4
Don't forget that I am using generics in my original example. This is absolutely useless if I use composition on the level of multi- and div- calculators. Imagine it to look like this:



I would need a Calculator for every SuperType possible then.. In addition, your example shows exactly my point. You need to implement the "add" function (and if its just to delegate..) and the "subtract" function in both, MultiCalc and DivCalc.. that's exactly what i would like to avoid.

My goal would be that only the very concrete leafs in the hierachy-tree would have to implement the abstract functions of all their ancestors
Matthew Brown
Bartender

Joined: Apr 06, 2010
Posts: 4467
    
    8

It might be worth having a look at the Bridge pattern. There's an object-oriented principle that classes really ought to vary for only one reason, and if you need to vary for more than one reason the suggested approach is to factor out the bits that vary and use composition.

I think my general approach would be something along the lines of:
- Define interfaces for the methods (or groups of methods) that you need to be able to vary independently of the others.
- Define (concrete) classes to encapsulate any common implementations
- For your final concrete classes, implement the interfaces you need to, and delegate to the utility classes as appropriate.

Which does sound a bit like what Jeff is suggesting. Yes, you might need to add quite a bit of delegating code, but that can't be helped. Each "proper" implementation will only be written once (and I'm assuming in real example these will be more complicated than "a + b"). And if the generic types you're interested in have stuff in common you may be able to group them in some way.

If you can trim down your original example to the essentials it might be easier to suggest an implementation, because it sounds like the calculator example wasn't a close enough match - but here's a calculator implementation with some generics included.
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 8244
    
  23

Christian Heupel wrote:I would need a Calculator for every SuperType possible then...

I don't think you would, but what you might need is some sort of ResultType interface. I've actually added an 'Arithmetic' interface myself, which could theoretically be implemented by most of the java.lang.Number classes, because all it does is define
T add(T value);
T subtract(T value);
T multiply(T value);
and
T divide(T value);
which most of them already implement.

Further to the good advice that you've already received, I'd just add that when you've got your interfaces sorted out, you might want to look at abstract skeleton implementations. I'm a great believer in them, and it may help to reduce the effort in implementing your 'leaf' classes. The Java Collections Framework contains a lot of good examples (Collection←AbstractCollection, List←AbstractList, etc). It does take a bit of work to get them right though

HIH

Winston

PS: If you could break up some those enormous lines in your code, it would make everything a lot easier to read. Thanks.


Isn't it funny how there's always time and money enough to do it WRONG?
Articles by Winston can be found here
Jeff Verdegan
Bartender

Joined: Jan 03, 2004
Posts: 6109
    
    6

Christian Heupel wrote:Don't forget that I am using generics in my original example.


I ignored that part because it didn't seem relevant to the overall design solution. At this point, I have to conclude that either you're misunderstanding something, or I am, and your issue is more complex than I had initially thought. I'll let others take up the torch from here. Good luck!
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39869
    
  28
Winston Gutkowski wrote: . . . PS: If you could break up some those enormous lines in your code, it would make everything a lot easier to read. Thanks.
I’ve done that. It might make it worse, since the original code mixes tabs and spaces
Christian Heupel
Greenhorn

Joined: Mar 15, 2012
Posts: 4
Hello together,

while sleeping a bit over this topic, I realized that I made it more complex in my head than it is and you are all absolutely right (of course.. ^^)

About the formatting: Sorry if there is some inconvenience, how should it be formatted best (for future posts)? I'm a little surprised that it should contain spaces as well (except of the short example, which shouldn't contains tabs because i just wrote it in here and tabs didn't work).

Once again, thanks for discussing on this and bringing some light into ;-)

Best,
Christian

 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
 
subject: Inheritance / Komposition of multiple abstract classes