Episode 3.5: Interfaces - Usable for Skills & Effects
Goal: Introduce interfaces as a second form of abstraction and use them to unify actions like using skills or applying effects.
Why Interfaces?
So far we used abstract class like Hero or Skill for abstraction. Now we’ll use interface to:
- Define shared behaviors without forcing class inheritance
- Enable multiple inheritance
Increase flexibility and decoupling
1. Project Structure
Create the following folder layout:
1
2
3
4
5
6
model/
├── Usable.java // (new)
├── Skill.java // implements Usable
effect/
├── StatusEffect.java // (optionally implements Usable)
2. Define the Usable Interface
Create a new interface in model/Usable.java:
1
2
3
4
5
package model;
public interface Usable {
void use(Hero caster, Hero target);
}
It defines a common behavior for any object that can be “used”
This could be a skill, a status effect, or even a consumable item in future updates
3. Update Skill to Implement Usable
Now your Skill abstract class will implement the interface:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package model;
public abstract class Skill implements Usable {
protected String name;
protected int damage;
public Skill(String name, int damage) {
this.name = name;
this.damage = damage;
}
public String getName() {
return name;
}
public abstract void use(Hero caster, Hero target);
}
Now every subclass of Skill must implement use() from the interface We’re enforcing a contract: all skills are “usable”
4. Optional: Let StatusEffect Also Implement Usable
If you want status effects to be applied directly (e.g., in spells), this is useful:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package effect;
import model.Hero;
import model.Usable;
public abstract class StatusEffect implements Usable {
protected int duration;
public StatusEffect(int duration) {
this.duration = duration;
}
public abstract void apply(Hero target);
public boolean isExpired() {
return duration <= 0;
}
public void tick() {
duration--;
}
@Override
public void use(Hero caster, Hero target) {
target.addEffect(this);
}
}
Abstract Class vs Interface: Key Differences
Feature | abstract class | interface |
---|---|---|
Has fields | Yes | No (except constants) |
Constructors | Yes | No |
Multiple inheritance | No | Yes |
Default method (Java 8+) | Yes | Yes |
Purpose Share state + behavior Define a contract for behavior