This achieves what I want (I have abstracted the implementation of "reportProblem"). But I know this is not the best way to do it. One reason is that the "reportProblem" method should not be called without calling "setName" and "setNumWheels" methods. Otherwise 'null' will be passed. Is there a way of enforcing, using some OOP technique, the two methods calls (setName and setNumWheels) BEFORE reportProblem is called?

I hope I have made myself clear. If I am not, just let me know how you would have done it so that I can learn from it.

Also, public fields are not good OO practice, because they expose details of your class' implementation that could be modified by users of the class. Those fields should be private. If the clients of the class need to know about them (or change them), then you should allow public getter (or setter) methods.

In Car, if I create a member variable - private final String mCar = "Car"; and then pass it in the constructor as super(mCar, 4);, why do I get the following error - Cannot refer to an instance field mCar while explicitly invoking a constructor
–
MediumOneApr 17 '12 at 12:49

Because it is not possible to pass an instance field (or an instance method call) to super(). You can only pass constructor parameters, static fields/method calls. Try with private static final String mCar = "Car";
–
TonyApr 17 '12 at 14:02

What is the point of a private default constructor? Why not just not include it? Generally a private constructor should only be used in a class that has a static factory method or in a utility class with only static methods and therefore no need for an instance to ever be created.
–
John BApr 17 '12 at 12:13

Thanks! I got it! I assigned the name and numWheels in the Truck/Car contructors! Now, I don't have to set them again in Test.java. In fact, we don't even need the set methods (setName and setNumWheels) in Vehicle! But I don't understand why I need to set them as private.
–
MediumOneApr 17 '12 at 12:14

@MediumOne it is considered poor OO practice to expose the implementation of a class. This includes access to fields. The case for this is generally two statements. First, if you decide you want to change field names for your implementation (change an int to an Integer, etc) you don't want to affect users. If access is limited to a getter method your impact is more limited. Second, you want to be able to control the manipulation of fields via a setter to allow for validation (ensure something isn't set to null). That said, public final is safe but not good practice.
–
John BApr 17 '12 at 12:20

@John: The aim of the private constructor is to prevent the creation of the Car/Truck objects without the fields setted. Now combined with the public constructor with arguments, you can have evolutive objects (let's say you want to instanciate a truck with 4 wheels) instead of "static" objects you have with your method.
–
TonyApr 17 '12 at 12:21

2

You are missing the point. If there is a constructor with arguments Java does not provide a default constructor so there is no need to hide it. Again, what is the point of a private constructor of an abstract class? It can NEVER be called.
–
John BApr 17 '12 at 12:24

If members are essentials for an object's state/functionality, put them as part of a constructor, so it is not possible to create an object (and call the method of concern) without providing proper values for these members.
But you should not also provide a no-args constructor.
If there are too many parameters needed consider looking into the Builder idion

In addition to @Tony's answer (+1) if you have to use bean notation (default constructor and setters) and still do not want to allow using any business methods before the object is initialized you can do the following.

Define abstract method checkInitalized() in your Vehicle class. Implement this methods for your Car and Truck. BTW this method will probably have default implementation in Vehicle. In this case do not forget to call super from its overridden versions.

checkInitalized() should throw exception (e.g. IllegalStateException) if not all required fields are initialized.
Now call this method in the beginning of each business method. This will prevent you from using object that is not initialized yet.

This technique is a little bit verbose. Probably using wrapper pattern or AOP (e.g. AspectJ) may be useful here.