I know that an interface could be used if there are no concrete methods. But what if you're trying to define an inheritance tree? It is my understanding that abstract classes are used to define inheritance trees while interfaces are thought of as not being tied to a particular inheritance tree. I usually hear that abstract classes are to be used when some common functionality can be factored out of a set of classes. What if there is no common functionality, but you want to create a superclass for polymorphism? Would a good designer ever do this?
But what if you're trying to define an inheritance tree? It is my understanding that abstract classes are used to define inheritance trees
Why would you want to define an abstract inheritance tree? Inheritance or deep class hierarchies are not, in themselves, desirable design features of an object-oriented application; there is inevitably tighter coupling between super- and subclasses than between a class and an associated collaborating class.
I usually hear that abstract classes are to be used when some common functionality can be factored out of a set of classes.
Right -- but for this to happen, you have to have the classes and their shared, common functionality first -- then, and only then, can you refactor common stuff into either (i) a superclass, or (ii) an independent collaborating class.
What if there is no common functionality, but you want to create a superclass for polymorphism? Would a good designer ever do this?
Nope, because if there is no common functionality (let's start using the word "behavoiur" here) then there is no need for polymorphism. You don't want to be doing polymorphism just for buzzword compatibility.
If, however, you do indeed have a set of classes that you wish to be able to treat polymorphically, then you do actually have similar behaviour across them; but here, then, you could more cleanly go with an interface. [ September 29, 2004: Message edited by: Allan Halme ]
<i>The lyf so short, the craft so long to lerne.</i> --Geoffrey Chaucer (c. 1343-1400)
What you say in your last paragraph was what I was getting at. I'll take an example from Head First Java (chapter 7) where an inheritance tree is designed for an Animal simulation program. Class Animal has four methods: makeNoise(), eat(), sleep(), and roam(). According to the design, the only concrete method for the Animal class is sleep(), while the other methods can only be meaningfully implemented in the subclasses (Lion, Hippo, etc.). What if someone later realizes that Lions sleep in the tall grass and Hippos sleep partially submerged in water, and that this information should be included in the simulation program? In other words, it is later decided that functionality should be added to sleep(), and the functionality will be different for each subclass, so that now sleep() becomes an abstract method like all the others. Then we would have an abstract class with no concrete methods. Are you saying that the Animal class should then be turned into an interface?
An object can be defined using two aspects: structure and behavior.
If there are a bunch of object types (or classes) that have a common structure, then you abstract the structure in the form of an abstract class.
If there are a bunch of object types (or classes) that have a common behavior, then you abstract the behavior in the form of an interface.
In your Animal example, I would ask myself the question - do I have some structure that is common to the subclasses that I need to abstract? Typically such common structure can be found in terms of attributes or relationships with other classes, like eyes, ears, etc.
If my answer is yes, then I would go for an abstract class instead of an interface. This is because it lets me use all these parameters in my subclasses (along with methods, if possible).
If my answer is no, then I would go for an interface.