Master Java's contract system and inheritance architecture through visual comparisons, design patterns, and real-world implementations
By the end of this lesson, you will:
<aside> 📋
Interface Philosophy
Interfaces are like business contracts - they define what must be done without specifying how to do it. Abstract classes are like architectural blueprints - they provide both the contract and some foundational implementation.
</aside>
Interface vs Abstract Class Architecture
══════════════════════════════════════════════════════════════════════════════════
📋 INTERFACE 🏗️ ABSTRACT CLASS
┌─────────────────┐ ┌─────────────────────┐
│ CONTRACT │ │ BLUEPRINT │
│ │ │ │
│ ✅ What to do │ │ ✅ What to do │
│ ❌ How to do it │ │ ✅ How to do some │
│ │ │ ❌ How to do all │
│ • All abstract │ │ │
│ • Multiple │ │ • Mixed concrete │
│ inheritance │ │ & abstract │
│ • Pure contract │ │ • Single inherit │
└─────────────────┘ │ • Partial blueprint │
│ └─────────────────────┘
▼ ▼
🎭 "CAN-DO" Behavior 🧬 "IS-A" Relationship
┌─────────────────┐ ┌─────────────────────┐
│ Flyable │ │ Animal │
│ Swimmable │ │ ├─ Mammal │
│ Drawable │ │ ├─ Bird │
│ Serializable │ │ └─ Fish │
└─────────────────┘ └─────────────────────┘
Capabilities Family Tree
Complete Interface Structure - The Evolution
═════════════════════════════════════════════════════════════════════════════════
📋 Modern Interface (Java 9+)
┌─────────────────────────────────────────┐
│ │
│ 🔸 Constants (public static final) │ ← Always constant
│ 🔸 Abstract methods (public abstract) │ ← Must implement
│ 🔸 Default methods (public default) │ ← Can override
│ 🔸 Static methods (public static) │ ← Call via Interface.method()
│ 🔸 Private methods (private) │ ← Helper methods (Java 9+)
│ │
└─────────────────────────────────────────┘
│
▼
📱 Implementation Classes
┌─────────────────────────────┐
│ • Must implement abstract │
│ • Can override default │
│ • Cannot access private │
│ • Cannot override static │
└─────────────────────────────┘
// 🎮 Modern gaming interface with all method types
public interface GameCharacter {
// 🔸 Constants - shared game configuration
String GAME_VERSION = "1.0.0";
int MAX_LEVEL = 100;
int DEFAULT_HEALTH = 100;
// 🔸 Abstract methods - must be implemented by all characters
void attack(GameCharacter target);
void defend();
int getHealth();
int getLevel();
// 🔸 Default methods - common behavior with option to override
default void levelUp() {
System.out.println(getName() + " leveled up to level " + (getLevel() + 1) + "!");
restoreHealth();
System.out.println("Health restored to full!");
}
default void restoreHealth() {
System.out.println(getName() + " health restored to " + DEFAULT_HEALTH);
// Implementation would set health to max
}
default void displayStats() {
System.out.println("📊 Character Stats:");
System.out.println(" Name: " + getName());
System.out.println(" Level: " + getLevel());
System.out.println(" Health: " + getHealth());
System.out.println(" Type: " + getCharacterType());
}
default boolean isAlive() {
return getHealth() > 0;
}
// 🔸 Static methods - utility methods for the interface
static GameCharacter createRandomCharacter() {
String[] types = {"Warrior", "Mage", "Archer", "Rogue"};
String randomType = types[(int) (Math.random() * types.length)];
System.out.println("🎲 Creating random " + randomType + " character...");
return switch (randomType) {
case "Warrior" -> new WarriorCharacter("RandomWarrior");
case "Mage" -> new MageCharacter("RandomMage");
case "Archer" -> new ArcherCharacter("RandomArcher");
default -> new RogueCharacter("RandomRogue");
};
}
static void printGameInfo() {
System.out.println("🎮 Game Version: " + GAME_VERSION);
System.out.println("🏆 Max Level: " + MAX_LEVEL);
System.out.println("❤️ Default Health: " + DEFAULT_HEALTH);
}
static boolean isValidLevel(int level) {
return level >= 1 && level <= MAX_LEVEL;
}
// 🔸 Private methods (Java 9+) - internal helpers
private void logAction(String action) {
System.out.println("[" + [java.time.LocalTime.now](<http://java.time.LocalTime.now>)() + "] " +
getName() + " performed: " + action);
}
private String formatHealthBar() {
int health = getHealth();
int barLength = 20;
int filledBars = (health * barLength) / DEFAULT_HEALTH;
StringBuilder healthBar = new StringBuilder("[");
for (int i = 0; i < barLength; i++) {
if (i < filledBars) {
healthBar.append("█");
} else {
healthBar.append("░");
}
}
healthBar.append("]");
return healthBar.toString();
}
// Abstract methods that need implementation
String getName();
String getCharacterType();
}
// 🗡️ Warrior Implementation
public class WarriorCharacter implements GameCharacter {
private String name;
private int level;
private int health;
private int armor;
private String weapon;
public WarriorCharacter(String name) {
[this.name](<http://this.name>) = name;
this.level = 1;
[this.health](<http://this.health>) = DEFAULT_HEALTH;
this.armor = 50;
this.weapon = "Iron Sword";
}
@Override
public void attack(GameCharacter target) {
if (!isAlive()) {
System.out.println("💀 " + name + " cannot attack - defeated!");
return;
}
int damage = 25 + (level * 2);
System.out.println("⚔️ " + name + " attacks " + target.getName() +
" with " + weapon + " for " + damage + " damage!");
// In a real game, this would reduce target's health
if (target instanceof WarriorCharacter warrior) {
warrior.takeDamage(damage);
}
}
@Override
public void defend() {
System.out.println("🛡️ " + name + " raises shield! Armor: " + armor);
// Defense implementation would reduce incoming damage
}
// Warrior-specific method
public void takeDamage(int damage) {
int actualDamage = Math.max(0, damage - (armor / 10));
health -= actualDamage;
health = Math.max(0, health);
System.out.println("💥 " + name + " takes " + actualDamage +
" damage (blocked " + (damage - actualDamage) +
") - Health: " + health);
}
// Warrior can override default levelUp behavior
@Override
public void levelUp() {
GameCharacter.super.levelUp(); // Call default implementation
// Add warrior-specific level up bonuses
armor += 5;
System.out.println("🛡️ Armor increased to " + armor + "!");
if (level % 5 == 0) {
upgradeWeapon();
}
}
private void upgradeWeapon() {
String[] weapons = {"Iron Sword", "Steel Sword", "Mithril Sword", "Legendary Blade"};
int weaponIndex = Math.min(level / 5, weapons.length - 1);
weapon = weapons[weaponIndex];
System.out.println("⚔️ Weapon upgraded to " + weapon + "!");
}
// Required implementations
@Override
public String getName() { return name; }
@Override
public String getCharacterType() { return "Warrior"; }
@Override
public int getHealth() { return health; }
@Override
public int getLevel() { return level; }
public int getArmor() { return armor; }
public String getWeapon() { return weapon; }
}
// 🔮 Mage Implementation with different behavior
public class MageCharacter implements GameCharacter {
private String name;
private int level;
private int health;
private int mana;
private String[] spells;
public MageCharacter(String name) {
[this.name](<http://this.name>) = name;
this.level = 1;
[this.health](<http://this.health>) = DEFAULT_HEALTH - 20; // Mages have less health
this.mana = 100;
this.spells = {"Magic Missile", "Fireball", "Lightning Bolt"};
}
@Override
public void attack(GameCharacter target) {
if (!isAlive()) {
System.out.println("💀 " + name + " cannot cast - defeated!");
return;
}
if (mana < 10) {
System.out.println("🔮 " + name + " is out of mana!");
return;
}
String spell = spells[(int) (Math.random() * spells.length)];
int damage = 30 + (level * 3);
mana -= 10;
System.out.println("🔮 " + name + " casts " + spell + " at " +
target.getName() + " for " + damage + " magic damage! (Mana: " + mana + ")");
}
@Override
public void defend() {
if (mana >= 15) {
mana -= 15;
System.out.println("✨ " + name + " casts Magic Shield! (Mana: " + mana + ")");
} else {
System.out.println("🏃 " + name + " attempts to dodge!");
}
}
// Mage-specific mana restoration
public void meditate() {
mana = Math.min(100, mana + 25);
System.out.println("🧘 " + name + " meditates and recovers mana: " + mana);
}
// Override default behavior for mages
@Override
public void levelUp() {
GameCharacter.super.levelUp(); // Call default
// Mage-specific bonuses
mana += 20;
System.out.println("🔮 Max mana increased to " + mana + "!");
if (level % 3 == 0) {
learnNewSpell();
}
}
private void learnNewSpell() {
String[] advancedSpells = {"Meteor", "Ice Storm", "Chain Lightning", "Teleport"};
String newSpell = advancedSpells[(int) (Math.random() * advancedSpells.length)];
System.out.println("📚 " + name + " learned new spell: " + newSpell + "!");
}
// Required implementations
@Override
public String getName() { return name; }
@Override
public String getCharacterType() { return "Mage"; }
@Override
public int getHealth() { return health; }
@Override
public int getLevel() { return level; }
public int getMana() { return mana; }
}