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
:(>)
@OverrideThe 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.