Nathan Sprague
We are developing a super-fun text-based video game:
public class Creature {
private int xPos;
private int yPos;
private int health;
public Creature(int xPos, int yPos, int health) {
this.xPos = xPos;
this.yPos = yPos;
this.health = health;
}
public String makeFace() {
return "OvO";
}
public int getXPos() {
return xPos;
}
public int getYPos() {
return yPos;
}
public void setXPos(int xPos) {
this.xPos = xPos;
}
public void setYPos(int yPos) {
this.yPos = yPos;
}
public int getHealth() {
return health;
}
public void setHealth(int health) {
this.health = health;
}
}
What’s wrong with this design so far?
What is the solution?
|
public class Monster extends Creature { // NOTICE THE "extends" KEYWORD!
private int xPos;
private int yPos;
private int health;
private boolean angry;
public Monster(int xPos, int yPos, int health) {
super(xPos, yPos, health); // Notice the call to superclass constructor
this.xPos = xPos;
this.yPos = yPos;
this.health = health;
this.angry = false;
}
public String makeFace() {
if (angry) {
return ":(>)" + " " + health;
} else {
return ":)" + " " + health;
}
}
public void setHealth(int health) {
angry = health < 3;
this.health = health;
}
}
What will be printed by this code snippet:
Monster monster = new Monster(50, 50, 10);
System.out.println(monster.getHealth());
System.out.println(monster.makeFace());
monster.setHealth(1);
System.out.println(monster.getHealth());
System.out.println(monster.makeFace())
10
:) 10
10
:(>) 1
10
:) 10
10
:) 10
10
:) 10
1
:(>) 1
10
:) 10
1
:) 10
setHealth
MethodWe want the Monster to become angry when its health falls below 3.
Which implementation works?
public class Monster extends Creature
{
private boolean angry;
public Monster(int xPos, int yPos, int health) {
super(xPos, yPos, health);
this.angry = false;
}
public String makeFace() {
if (angry) {
return ":(>)";
} else {
return ":)";
}
}
public void setHealth(int health) {
angry = health < 3;
super.setHealth(health); // health instance variable is private!
}
public class Monster extends Creature {
private boolean angry;
public Monster(int xPos, int yPos, int health) {
super(xPos, yPos, health);
this.angry = false;
}
public String makeFace() {
if (angry) {
return ":(>)";
} else {
return ":)";
}
}
public void setHealth(String health) {
super.setHealth(Integer.parseInt(health));
angry = getHealth() < 3;
}
What will be printed by the following code snippet?
Monster monster = new Monster(50, 50, 10);
monster.setHealth(1);
System.out.println(monster.getHealth());
System.out.println(monster.makeFace());
monster.setHealth("2");
System.out.println(monster.getHealth());
System.out.println(monster.makeFace())
1
:(>)
2
:(>)
10
:)
2
:(>)
1
:)
1
:)
1
:)
2
:(>)
@Override
The problem here is that the author intended to override the setHealth method of the superclass, but overloaded it instead.
This type of error can be avoided by using the @Override
annotation. It informs the compiler that you intend a method to override a method defined in the superclass.
This wouldn’t compile, because Creature
has no method with this signature.
Let’s add a toString
method to Creature
:
public class Creature
{
// Other code not shown.
public String toString() {
return makeFace() + " " + xPos + " " + yPos;
}
}
What will be printed when this code snippet executes?
Creature c1 = new Creature(20, 30, 10);
Monster m1 = new Monster(15, 17, 8);
System.out.println(c1);
System.out.println(m1);
OvO 20 30
OvO 15 17
OvO 20 30
:) 15 17
B. Calling makeFace
on an object of type Monster
will always execute the Monster
version of the method.