So far we used abstract class like Hero or Skill for abstraction. Now we’ll use interface to:
Increase flexibility and decoupling
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)
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
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”
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