The Constructor#
Let's take this Label
class (second tab) as an example. It has three attributes and can draw a label with its .show()
method.
class Label {
float size;
String text;
int backgroundColor;
void show() {
push();
// preparations
translate(0, -(size+10)/2);
noStroke();
textSize(size);
float width = textWidth(text);
// background
fill(backgroundColor);
rect(size, 0, width + 10, size + 10);
triangle(size, 0, size, size + 10, 0, (size+10)/2);
// text
fill(0, 0, 0);
text(text, size + 5, size * 0.85 + 5);
pop();
}
}
The Main Code Creates a new object of type Label
in a variable called city
. We later set the three attributes, and finally draw()
will call city.show()
to actually draw the results to the screen.
But in between creating our instance in line 1 and setting the .text
, .size
and .backgroundColor
in the setup()
-function, this object is "broken". None of the information is available, and if we instead did this:
We would be presented with a NullPointerException
error, because we're trying to draw a text we haven't even set, yet! Wouldn't it be cool, if the created object was working right from the start? That is, where the constructor can help you.
Default Constructor#
A constructor is what's running when you create a new instance. In all our previous examples, we were using constructors, we just didn't see them, because we did not write our own constructors. In those cases, Java just creates an empty object.
This is also, why instantiating a new object looks a little bit like a function call. Label city = new Label();
specifically that second part with the parentheses! The constructor is what returns our new object.
Creating Your Own Constructor#
Let's say we always want our label to at least not break anything. We should set default values for .text
, .backgroundColor
and size
and we can do this by providing our own constructor which replaces that default constructor:
class Label {
float size;
String text;
int backgroundColor;
Label() {
size = 20.0;
text = "";
backgroundColor = #d0d0d0;
}
void show() {
push();
// preparations
translate(0, -(size+10)/2);
noStroke();
textSize(size);
float width = textWidth(text);
// background
fill(backgroundColor);
rect(size, 0, width + 10, size + 10);
triangle(size, 0, size, size + 10, 0, (size+10)/2);
// text
fill(0, 0, 0);
text(text, size + 5, size * 0.85 + 5);
pop();
}
}
That newly created thing looks a little bit like a function without a return type. It is also weirdly named with a capital letter and therefore has the exact same name as the class itself. Congratulations, these two things (no return type and same name as the class) are what makes this a constructor!
No Return Type for the Constructor
A constructor will return our newly created object, so for some reason it has to be written with no return type at all. But we're also not calling return
anywhere. It just returns the object anyway.
Constructor with Parameters#
Since this looks so much like a function call, let's try adding Parameters!
class Label {
float size;
String text;
int backgroundColor;
Label(String labelText) {
size = 20.0;
text = labelText;
backgroundColor = #d0d0d0;
}
void show() {
push();
// preparations
translate(0, -(size+10)/2);
noStroke();
textSize(size);
float width = textWidth(text);
// background
fill(backgroundColor);
rect(size, 0, width + 10, size + 10);
triangle(size, 0, size, size + 10, 0, (size+10)/2);
// text
fill(0, 0, 0);
text(text, size + 5, size * 0.85 + 5);
pop();
}
}
With this change to our constructor, we can now set the text in the exact moment that this object gets created. In fact we have to set a text (even if it's an empty text). Because the constructor demands a parameter.
Of course we can still modify the attributes later-on.
Constructors are Powerful
Using a constructor is often a good idea. You get to set up default values and other internal things. You can make sure your object has everything correctly set up before anyone gets to see it.