public class Monster extends Entity {
// extra fields or methods for Monster can go here
}
Subsection8.6.1A Complete Inheritance Example
Below is a fuller example. The superclass Entity stores a health field, plus methods for initializing and modifying this health. The subclass Player automatically gains those fields and methods, but also adds its own unique ones.
// File: Entity.java
public class Entity {
protected int health;
protected int maxHealth;
protected String name;
public Entity(String name, int initialHealth) {
this.name = name;
this.maxHealth = initialHealth;
this.health = initialHealth;
}
public void takeDamage(int amount) {
// Common damage calculation logic
health -= amount;
if (health < 0) {
health = 0;
}
System.out.println(name + " takes " + amount + " damage. Health: " + health);
}
public void heal(int amount) {
health += amount;
if (health > maxHealth) {
health = maxHealth;
}
System.out.println(name + " heals for " + amount + ". Health: " + health);
}
public int getHealth() {
return health;
}
public String getName() {
return name;
}
}
// File: Player.java
public class Player extends Entity {
private int experiencePoints;
private int level;
public Player(String playerName, int initialHealth) {
super(playerName, initialHealth); // calls the Entity constructor
this.experiencePoints = 0;
this.level = 1;
}
public void gainExperience(int points) {
experiencePoints += points;
System.out.println(getName() + " gains " + points + " experience points!");
// Level up if enough experience is gained
if (experiencePoints >= level * 100) {
levelUp();
}
}
private void levelUp() {
level++;
maxHealth += 10; // Increasing maximum health on level up
health = maxHealth; // Full heal on level up
System.out.println(getName() + " levels up to level " + level + "!");
}
public void printStatus() {
System.out.println("Player: " + getName() + ", Level: " + level +
", Health: " + getHealth() + "/" + maxHealth +
", XP: " + experiencePoints);
}
}
When Player calls super(playerName, initialHealth), it runs the Entity constructor to set up the parent class fields. Thanks to inheritance, you don’t need to duplicate the health variable or takeDamage() method in Player. You inherit them all from Entity, while adding player-specific behaviors like gaining experience and leveling up.
Java has three main access modifiers for fields and methods. We’ve already seen and used private (accessible only within the same class), public (accessible from any class). The third access modifier is protected which makes methods and fields accessible within the same class, subclasses, and classes in the same package.
In Java, a package is a way of organizing related classes and interfaces into a namespace to prevent naming conflicts and control access. It serves as a logical grouping mechanism, similar to folders in a file system. We’ve already been using packages when we import built-in Java classes (e.g., import java.util.ArrayList;) and external libraries. This allows us to access functionality without needing to define everything from scratch. To use a class from a different package, you must import it using the import statement or refer to it using its fully qualified name. Later, we will learn more about how to organize our own code into packages to improve maintainability and structure.
In the example above, health is declared protected. That means subclasses of Entity can access it directly. If health were private, then only the Entity class itself could access health, and subclasses would need methods like getHealth() to interact with it.
Default to private fields with accessor methods (getters/setters). This maintains better encapsulation and gives you more control over how fields are accessed and modified. Use protected sparingly and only when subclasses truly require direct field access for well-justified reasons.