Post

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.

Episode 3.5: Interfaces - Usable for Skills & 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

Featureabstract classinterface
Has fieldsYesNo (except constants)
ConstructorsYesNo
Multiple inheritanceNoYes
Default method (Java 8+)YesYes

Purpose Share state + behavior Define a contract for behavior

This post is licensed under CC BY 4.0 by the author.