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;
}
}
Of course... the game will need several different creature types. Let's add a monster class with a different appearance:
public class Monster
{
private int xPos;
private int yPos;
private int health;
private boolean angry;
public Monster(int xPos, int yPos, int health)
{
this.xPos = xPos;
this.yPos = yPos;
this.health = health;
this.angry = false;
}
public String makeFace()
{
if (angry)
{
return ":(>)";
}
else {
return ":)";
}
}
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)
{
angry = health < 3;
this.health = health;
}
}
What's wrong with this class?
What is the solution?
Monster
"is-a" Creature
.
Monster
inherits all Creature
attributes.Monster
can have additional methods and variables.Monster
can override existing methods.public class Monster extends Creature
{
private int xPos;
private int yPos;
private int health;
private boolean angry;
public Monster(int xPos, int yPos, int health)
{
super(xPos, yPos, health);
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
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)
{
//...
}
setHealth
MethodWe want the Monster to become angry when its health falls below 3.
Which implementation works?
public void setHealth(int health)
{
angry = health < 3;
this.health = health;
}
public void setHealth(int health)
angry = health < 3;
setHealth(health);
}
public void setHealth(int health)
angry = health < 3;
super.setHealth(health);
}
public void setHealth(int health)
angry = health < 3;
super.health = health;
}
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);
}
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.
@Override
public void setHealth(String health)
{
super.setHealth(Integer.parseInt(health));
angry = getHealth() < 3;
}
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.