Index

Let's try using some interfaces to see if it helps with our failed first try.

Review of Failure Point


We'll first review our failure point, and solve the problem from that point down.

Failure Point
Recall: "Object" does not understand "getWeight".

We simply need something that does understand "getWeight". That would solve this problem.

As coders, the nice thing is when we need a new type to do something, we can simply code it up a new class. Interfaces give us yet another approach to add new types.
public int getTotalWeight()  {
	int totalWeight = 0;
	for (Object eachObject: this.objects)
		totalWeight += eachObject.getWeight();
	return totalWeight;
}

A New Tool: Interface


A Java interface is very much like a class from the usage perspective. As a matter of fact, let's generalize class and interface, and just think of them both as "types". E.g. example "types" might be: List, String, Rectangle, Professor, etc.

Propose a New Type


public int getTotalWeight()  {
	int totalWeight = 0;
	for (Object eachObject: this.objects)
		totalWeight += eachObject.getWeight();
	return totalWeight;
}
public int getTotalWeight()  {
	int totalWeight = 0;
	for (Weighable eachObject: this.objects)
		totalWeight += eachObject.getWeight();
	return totalWeight;
}


Design the New Type


The first cut at our proposed type is that it is named Weighable, and we know it must understand this method:
public final int getWeight()


A Simple Interface?


Weighable Interface
Here is the code for the "Weighable" interface. Please note the similarity to a "class" except:
  • The word "interface" is used instead of "class"
  • Method code (body) is not present (just the method header).

It is like a shell of a class. It is nice and lightweight.
public interface Weighable {
	public int getWeight();
}


Implementing the Interface


Now that we have a new type (interface) we need to tweak our classes so they "implement" the interface.

Elephant2
  • We simply add "implements Weighable" to the class header
  • We must have a method with a method header matching all methods in the interface (which we do)

Now:
  • Elephant2 "is-a" Weighable
  • Elephant2 understands the method "getTotalWeight"

We do similar for PopcornMachine2 as shown here...
#1
public class Elephant2 implements Weighable { private int weight; public Elephant2(int aWeight) { this.weight = aWeight; }
#2
public int getWeight()
{ return weight; } }
Zoo2
Only three tweaks here. We change our ivar "objects" to use the "Weighable" type. And then we change "Object" to "Weighable" in the code as needed (two places shown).
public class Zoo2 {
	private String name;
	private List<Weighable> objects;

	public Zoo2(String aName) {
		this.name = aName;
		this.objects = new ArrayList<>();
	}

	public void add(Weighable aObject) {
		this.objects.add(aObject);
	}

	public int getTotalWeight() {
		int totalWeight = 0;
		for (Weighable eachObject: this.objects)
			totalWeight += eachObject.getWeight();
		return totalWeight;
	}

	public String toString() {
		return String.format("%s -- Total Weight of Objects = %d",
								this.name, getTotalWeight());
	}

}

Bug Check
Please recall that we previously were bitten by a bug when we sent "getWeight". The bug is gone! 😊 Celebrate good times.
public int getTotalWeight()  {
	int totalWeight = 0;
	for (Weighable eachObject: this.objects)
		totalWeight += eachObject.getWeight();
	return totalWeight;
}

Zoo2Test


A code test can be found here....

Completed Code


Here are the completed classes:


Conclusion


  • Zoo is sending our specialized message "getWeight"
  • The receiver of the message is type "Weighable"

The specialized type "Weighable" does understand "getWeight". 😊

The change we made was very small as we'll see in the next diagram
Compare Try #2 to Try #1 Side-By-Side