Class Normalization talks about refactoring common data + behaviour into superclasses/superinterfaces.
Currently I am using an Abstract class to purely contain common data fields while subclasses will extend the Abstract class and add additional fields on their own. Is this a good move ?
Everyone knows that Abstract classes cannot be instantiated; but I currently have a non-abstract constructor that will take the inputs for the common data elements. This seems a bit strange but it compiles fine. The constructor of my subclasses will then do a
Note that having a constructor is a requirement of being a class. If you don't define a constructor for a class -- abstract or not -- the compiler will generate a public no-argument empty constructor for you. But having a constructor doesn't mean the class itself can be instantiated.
As well, all constructors up the chain of superclasses are executed no matter what. You cannot skip calling the superclass's constructor. Thus, since abstract classes must be extended to be used, and their subclasses must call the superclass's constructor, abstract classes must have a constructor.
In Java, there is no such thing as an abstract constructor, even if you wanted to have one. As David points out, even abstract classes need a way to initialize any data, so a constructor like this is very appropriate.
Therefore, there isn't much difference between an abstract class and a non-abstract class other than the fact the former cannot be instantiated. Of course, there wouldn't be much utility in abstract classes if you don't have any abstract methods.
I've been reading DDD by Eric Evans and he seems to frown upon my design above. In the chapter on Factories, he writes:
Avoid calling constructors within constructors of other classes. Constructors should be dead simple. Complex assemblies, call for FACTORIES.
I wonder if my aforementioned design fall into this category of constructors with "complex assemblies".
Joined: Aug 07, 2003
Originally posted by Pho Tek: I wonder if my aforementioned design fall into this category of constructors with "complex assemblies".
Domain-Driven Design is a very good book, and I agree with the general advice here.
The key to that quote is "constructors of other classes." As I said, you cannot avoid calling the superclass's constructor from the subclass's constructor. Well, you can actually, by calling a different constructor of the subclass which will then call a superclass constructor.
One goal of the Factory pattern is to have the Factory create classes and wire them together. This is unrelated to the discussion regarding abstract classes, though it is a worthy discussion.
An example would be a business object that requires two DAOs to do its work. The business object should not instantiate the two DAOs. Rather a BO Factory (or a framework like Spring) should instantiate the objects individually and set references between them appropriately. The following code is extremely trivial just to show how this applies.Of course, as with any design pattern you want to make sure you don't go off the deep end. If you have a class that uses an internal HashMap to fulfill its contract, you don't need a separate Factory to build that class and hand it a HashMap; that's going too far.
Excellent thread! You're probably doing just fine, but your very first idea - refactoring common code into a superclass - is not a blanket solution. Two classes with common code don't necessarily belong in an inheritance tree together. Someone here at work refactored all database processing in a smallish system into a root superclass. This gives a false "is-a" tree and prevents lower classes from extending something else more useful. The other choice is composition: everything that does database processing uses a common mechanism class. Much more flexible and reusable in the long run.
A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi