Thursday, September 25, 2008

Constructors revisited

"A class contains constructors that are invoked to create objects from the class blueprint.", says the lesson entitled Providing Constructors.

So where is the constructor in Hello World? Where is the constructor in the first bicycle?

For clarity, let's set out the code for the first bicycle (Version 1):

class Bicycle {
int cadence = 0;
int speed = 0;
int gear = 1;
void changeCadence(int newValue) {
cadence = newValue;
}
void changeGear(int newValue) {
gear = newValue;
}
void speedUp(int increment) {
speed = speed + increment;
}
void applyBrakes(int decrement) {
speed = speed - decrement;
}
void printStates() {
System.out.println("cadence:"+cadence+
" speed:"+speed+" gear:"+gear);

}
}

and lets compare this with the bicycle with constructor (Version 2):

public class Bicycle {
// the Bicycle class has three fields
public int cadence;
public int gear;
public int speed;
// the Bicycle class has one constructor
public Bicycle(int startCadence,
int startSpeed,
int startGear) {
gear = startGear;
cadence = startCadence;
speed = startSpeed;
}
// the Bicycle class has four methods
public void setCadence(int newValue) {
cadence = newValue;
}
public void setGear(int newValue) {
gear = newValue;
}
public void applyBrake(int decrement) {
speed -= decrement;
}
public void speedUp(int increment) {
speed += increment;
}
}

To my (Java-virgin) eyes, the essential difference between the two is that in Version 1, the fields cadence, speed, and gear are initialised upon declaration, but in Version 2 they are not. Instead you have this thing called a constructor which essentially does exactly that.

I concede that creating a bicycle with particular parameter values is quite neat from Version 2

Bicycle myBike = new Bicycle(30, 0, 8);

whereas to do the same from Version 1 is a bit more clumsy:

Bicycle bike1 = new Bicycle();
bike1.cadence = 30
bike1.speed = 0
bike1.gear = 8

Unless of course you have a class of objects which always (or nearly always) opens with the same values, in which case you simply plonk those values into the field declarations of Version 1 of the class. This is not an unreasonable assumption even in the case of a bicycle. Why should a bicycle not start with a zero cadence, zero speed, and in gear 1?

But this is all beside the point really. My criticism of the Java Tutorial in this lesson is not whether or not you can write neater code with or without a constructor. It is that the idea is badly introduced and poorly explained.

The opening sentence: "A class contains constructors that are invoked to create objects from the class blueprint" is confusing for many reasons, not least because we have seen classes without constructors and objects created without reference to them.

The fudge provided by the lesson to excuse this is: "Although Bicycle only has one constructor, it could have others, including a no-argument constructor". This is like saying a man with no legs has two no-leg legs. It's ugly and silly.

I don't have time or the inclination to rewrite the entire tutorial. I am still learning myself. But I can think of at least two ways to introduce the idea of a constructor more coherently, so the lessons flow better.

First in the What is a Class lesson, when Bicycle is invoked:

          // Create two different Bicycle objects           Bicycle bike1 = new Bicycle();           Bicycle bike2 = new Bicycle();

There could be an explicit reference to the brackets, and explanation as to how they can be used and why they are empty. And if it is poor coding practice not use constructors, then this should be explained sooner rather than later.

Second in Constructor lesson, don't open with a sentence which implies that this is the only way of doing things (which it patently isn't), but make an explicit reference Version 1 of the bicycle, and explain how adding a constructor to the class might in some circumstances make the code to create objects from the class neater.

And again, if there are other reasons for using constructors, such as that the compiler looks for them, then this should have been explained earlier, and it should be explained better and more fully, with examples of good code, and examples of code which will not compile.

No comments: