Object-Oriented Programming with Java, part I + II

cc

This material is licensed under the Creative Commons BY-NC-SA license, which means that you can use it and distribute it freely so long as you do not erase the names of the original authors. If you make changes in the material and want to distribute this altered version of the material, you have to license it with a similar free license. The use of the material for commercial use is prohibited without a separate agreement.

Authors: Arto Hellas, Matti Luukkainen
Translators to English: Emilia Hjelm, Alex H. Virtanen, Matti Luukkainen, Virpi Sumu, Birunthan Mohanathas, Etiënne Goossens
Extra material added by: Etiënne Goossens, Maurice Snoeren, Johan Talboom
Adapted for Informatica by: Ruud Hermans

The course is maintained by Technische Informatica Breda


Multiple constructors

Let us return to the class that handles Persons again. The class Person currently looks like this:

public class Person {

    private String name;
    private int age;
    private int height;
    private int weight;

     public Person(String name) {
        this.name = name;
        this.age = 0;
        this.weight = 0;
        this.height = 0;
    }

    public void printPerson() {
        System.out.println(this.name + " I am " + this.age + " years old");
    }

    public void becomeOlder() {
        this.age++;
    }

    public boolean adult(){
        if ( this.age < 18 ) {
            return false;
        }

        return true;
    }

    public double weightIndex(){
        double heightInMeters = this.height/100.0;

        return this.weight / (heightInMeters*heightInMeters);
    }

    public String toString(){
        return this.name + " I am " + this.age + " years old, my weight index is " + this.weightIndex();
    }

    public void setHeight(int height){
        this.height = height;
    }

    public int getHeight(){
        return this.height;
    }

    public int getWeight() {
        return this.weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    public String getName(){
        return this.name;
    }
}

All person objects are 0 years old at creation, since the constructor sets it to 0:

public Person(String name) {
    this.name = name;
    this.age = 0;
    this.weight = 0;
    this.height = 0;
}

We also want to create a person so that in addition to name, can be given an age as a parameter. This can be achieved easily, since multiple constructors can exist. Let us make an alternative constructor. You do not need to remove the old one.

public Person(String name) {
    this.name = name;
    this.age = 0;
    this.weight = 0;
    this.height = 0;
}

public Person(String name, int age) {
    this.name = name;
    this.age = age;
    this.weight = 0;
    this.height = 0;
}

Now, creating objects can be done in two different ways:

public static void main(String[] args) {
    Person pekka = new Person("Pekka", 24);
    Person esko = new Person("Esko");

    System.out.println( pekka );
    System.out.println( esko );
}
Pekka, age 24 years
Esko, age 0 years

The technique in which a class has two constructors is called constructor overloading. A class can have multiple constructors, which are different from one another according to parameter quanitities and/or types. However, it is not possible to create two different constructors that have exactly the same type of parameters. We cannot add a constructor public Person(String name, int weight) on top of the old ones, since it is impossible for Java to tell the difference between this one and the one in which the integer stands for the age.

Calling your own constructor

But wait, in chapter 21 we noted that “copy-paste” code is not too great of an idea! When we inspect the overloaded constructors above, we notice that they have the same code repeated in them. We are not ok with this.

The old constructor actually is a special case of the new constructor. What if the old constructor could ‘call’ the new constructor? This can be done, since you can call another constructor from within a constructor with this!

Let us change the old constructor that does nothing, but only calls the new constructor below it and asks it to set the age to 0:

public Person(String name) {
    this(name, 0);  // run here the other constructor's code and set the age parameter to 0
}

public Person(String name, int age) {
    this.name = name;
    this.age = age;
    this.weight = 0;
    this.height = 0;
}

Calling the own constructor of a class this(name, 0); might seem a little peculiar. But we can imagine that during the call it will automatically copy-paste the code from the constructor below and that 0 is entered to the age parameter.

Overloading a method

Just like constructors, methods can also be overloaded and multiple versions of a method can exist. Again, the parameter types of different versions have to be different. Let us create another version of the becomeOlder, which enables aging the person the amount of years that is entered as a parameter:

public void becomeOlder() {
    this.age = this.age + 1;
}

public void becomeOlder(int years) {
    this.age = this.age + years;
}

In the following, “Pekka” is born as a 24-year old, ages one year, and then 10:

public static void main(String[] args) {
    Person pekka = new Person("Pekka", 24);

    System.out.println(pekka);
    pekka.becomeOlder();
    System.out.println(pekka);
    pekka.becomeOlder(10);
    System.out.println(pekka);
}

Prints:

Pekka, age 24 years
Pekka, age 25 years
Pekka, age 35 years

Now, a person has two becomeOlder methods. The method that is chosen to be run depends on the amount of parameters entered in to the method call. The method becomeOlder can also be run through the method becomeOlder(int years):

public void becomeOlder() {
    this.becomeOlder(1);
}

public void becomeOlder(int years) {
    this.age = this.age + years;
}

Exercise constructors-1: Overloaded counter

Exercise constructors-1.1: Multiple constructors

Make a class Counter that holds a number that can be decreased and increased. The counter also has an optional check that prevents the counter from going below 0. The class has to have the following constructors:

  • public Counter(int startingValue, boolean check) creates a new counter with the given value. The check is on if the parameter given to check was true.
  • public Counter(int startingValue) creates a new counter with the given value. The check on the new counter should be off.
  • public Counter(boolean check) creates a new counter with the starting value 0. The check is on if the parameter given to check was true.
  • public Counter() creates a new counter with the starting value of 0 and with checking off. and the following methods:

  • public int value() returns the current value of the counter
  • public void increase() increases the value of the counter by one
  • public void decrease() decreases the value of the counter by one, but not below 0 if the check is on

Exercise constructors-1.2: Alternative methods

Create also a one parametered versions of the methods increase and decrease:

  • public void increase(int increaseAmount) increases the value by the amount of the parameter. If the value of the parameter is negative, the value will not change.
  • public void decrease(int decreaseAmount) decreases the value of the counter by the amount given by the parameter, but not below 0 if the check is on. If the value of the parameter is negative, the value of the counter will not change.