[tag]Java[/tag] has no support for [tag]multiple inheritance[/tag], right? At least that’s what you have been told. You can’t explicitly declare a class to be a child of two different unrelated classes. That is true. But you also need to remember that you can always walk up the inheritance tree which may give you a way to circumvent this rule.
Let me give you an example. I’m currently working on a multi-threaded matrix factorization algorithm. So I have a class called Factorizer which extends Thread and implements the logic of the algorithm. I needed to slightly modify this algorithm and change the logic in 2 or 3 methods. I really don’t like copying and pasting large volumes of code so I decided to simply inherit everything from Factorizer and then overload the methods where appropriate.
When I extend Factorizer, I implicitly inherit all the functionality of it’s parent which is Thread. This was essentially a no-brainer, but if you think about this in the end I ended up with a class that inherits from two wildly different parents.
But how to apply this logic to real life situations? Let’s try to come up with a good scenario when a multiple inheritance would be desirable. If you will, imagine that we have two classes called Camera and Phone:
public class Camera
{
public void snapPicture() { // lots of code }
}
public class Phone
{
public void makeACall(){ // lots of code }
}
You want to create a new class CameraPhone. Ideally you would want to inherit all the code from both classes so that you don’t have re-implement anything. Unfortunately in Java this is impossible. You could rewrite Phone as a child of Camera, or Camera as a child of Phone but neither one nor the other makes much sense with respect to the conceptual design. This is the type of conundrum that you may possibly encounter in Java world, albeit very rarely if ever. What do you do?
You go back to the drawing board and rethink your design. When dealing with single inheritance we usually want to design from the most general, to the most specific entity. We could argue that CameraPhone is a more general design element because both Phone and Camera can be defined as it’s sub elements. So if we flip the inheritance tree on its head, we get a classic, Java kosher, single inheritance. So lets put all the functional code in the parent:
public class CameraPhone
{
public void snapPictute() { // code }
public void makeACall() { // code }
}
Next we simply do what many manufacturers out there do when they decide to sell low end, cheep versions of their products – disable features:
public class Camera extends CameraPhone
{
public void makeACall() {}
}
public class Phone extends CameraPhone
{
public void snapPicture() {}
}
I’m simply overloading unnecessary methods with empty definitions, but you can probably do something more clever. For example you may return some default value, throw an exception, etc.. The best part is that both Phone and Camera will continue working in the same exact way they did before. Any code that depended on these classes being there will still work. But now we do have a class that combines characteristics of the two. Is this multiple inheritance? No, but it works. Would it be more logical to do it the other way around? Maybe, but who cares. This solution makes sense both conceptually, and code wise.
Any time you run into a multiple inheritance problem, try to think about it in terms of design. You can’t circumvent Java’s inheritance rules, but you can you can probably restructure your code to rout around this issue.
Update Fri, September 15 2006, 08:59 PM
Here is another solution suggested by ZeWrestler. Create a wrapper class that would include both Phone and Camera:
public class CameraPhone
{
private Camera c;
private Phone p;
public CameraPhone(Camera c, Phone p)
{
this.p=p; this.c=c;
}
public void makeACall() { p.makeACall(); }
public void snapPicture() { c.snapPicture(); }
}
This is probably the best thing to do if you just can’t modify the existing classes (for example, you have no access to their proprietary code). What is the downside here? You get a performance hit because instead of one method call you have two. If you can live with that, you should be fine. Also, you can’t down-cast CameraPhone back to Phone if you need to.
I think I can one-up that. The most elegant solution would be to create interfaces for both Phone and Camera:
public interface CameraInterface
{
public void makeACall();
}
public interface PhoneInterface
{
public void snapPicture();
}
You can now create Phone and Camera classes that implement appropriate interface. Finally when making your CameraPhone you implement both, and use wrapping as above:
public class CameraPhone implements PhoneInterface, CameraInterface
{
private Camera c;
private Phone p;
public CameraPhone(Camera c, Phone p)
{
this.p=p; this.c=c;
}
public void makeACall() { p.makeACall(); }
public void snapPicture() { c.snapPicture(); }
}
There you have it – an elegant solution to the problem with total code reuse, and only a small performance hit.
[tags]programming, inheritance[/tags]
I know its not the best solution, but what about declaring an object of both phone and camrea inside camreaphone. then have a bunch of accessor methods manipulating the variables for the 2 classes.
Good point! I think this would work equally well, but you would probably end up writing more code to redirect the method calls. But the big advantage of your method is that you don’t need to change any of the code for Camera and Phone classes, so I think this would be a fair tradeoff.
Actually, what we probably should have is an interface for Camera and an inteface for Phone. Both classes would implement the appropriate one. Then CameraPhone would implement both, and simply redirect the methods to the objects declared inside. That would probably be the most elegant solution.
Ze, I added your comments to the post. Thansk :)