10장 추상클래스와 인터페이스
1. 추상 클래스(Abstract Class)
추상 클래스는
abstract
키워드로 정의된 클래스입니다.완전하지 않은 설계도 같은 것으로, 일부 메서드는 구현하고, 일부 메서드는 선언만 해놓습니다.
특징
객체를 직접 생성할 수 없습니다.(완전한 설계도가 아니므로)
상속받은 자식 클래스가 추상 메서드를 반드시 구현해야 합니다.
필드, 구현된 메서드, 생성자를 가질 수 있습니다.
작성 방법
abstract class Animal {
String name;
// 추상 메서드 (선언만 함)
abstract void sound();
// 일반 메서드 (구현되어 있음)
void eat() {
System.out.println("먹이를 먹습니다.");
}
}
사용 예
class Dog extends Animal {
void sound() {
System.out.println("멍멍!");
}
}
Animal추상클래스를 상속시 Dog 클래스는 반드시 미구현 메서드인
sound()
메서드를 구현해야 합니다.
2. 인터페이스(Interface)
인터페이스는 기능(명세)만 정의하는 일종의 약속입니다.
모든 메서드가 기본적으로 추상 메서드입니다. (Java 8 이후 default 메서드 추가 가능)
특징
다중 상속이 가능합니다. (여러 인터페이스를 implements 가능)
implements
키워드를 사용해 구현합니다.필드는 모두 상수(public static final) 입니다.
작성 방법
interface Animal {
void sound(); // public abstract가 생략되어 있음
}
사용 예
class Cat implements Animal {
public void sound() {
System.out.println("야옹!");
}
}
인터페이스 구현(implements)시 인터페이스의 미구현 메서드인
sound()
메서드를 구현해야 합니다.
3. 추상 클래스 vs 인터페이스 차이점
상속
단일 상속만 가능
다중 상속 가능 (여러 개 구현 가능)
구성 요소
필드, 생성자, 일반 메서드, 추상 메서드 모두 가능
상수, 추상 메서드 (default/static 메서드도 가능)
사용 목적
공통된 기능 + 일부 강제 구현
전적으로 기능 명세 제공 (규칙 만들기)
키워드
extends
로 상속
implements
로 구현
기본 목적
설계 + 공통 기능 제공
설계(약속, 규칙)만 제공
4. 추상클래스와 인터페이스의 구분
다음 상황에 맞는 클래스를 만든다고 가정.
모든 게임 캐릭터는 이동(move)할 수 있고 공격(attack) 을 할 수 있다.
하지만, 공격하는 방식은 캐릭터마다 다름
검사는 검으로 베고,
궁수는 활로 쏘고,
마법사는 마법을 쓴다.
1. 추상클래스 사용 케이스
모든 클래스에 동일한 속성과 기능이 존재하면서, 각 클래스마다 반드시 존재해야 하지만 , 구현방법이 달라야하는 기능이 존재하는 경우 추상클래스를 만들어 상속시킨다.
예를 들어, 모든 게임캐릭터는 이름과, 레벨에 해당하는 공통속성을 가지고 있으며, 움직일 수 있는 기능을 가지고 있다. 하지만 캐릭터마다 공격하는 방식이 달라야 한다.
abstract class Character {
String name;
int level;
Character(String name, int level) {
this.name = name;
this.level = level;
}
void introduce() {
System.out.println("안녕하세요! 저는 " + level + "레벨 모험가 " + name + "입니다.");
}
abstract void attack(); // 공격은 각 캐릭터마다 다르게 구현
}
// 전사
class Warrior extends Character {
Warrior(String name, int level) {
super(name, level);
}
void attack() {
System.out.println(name + "가 검으로 베었습니다!");
}
}
// 궁수
class Archer extends Character {
Archer(String name, int level) {
super(name, level);
}
void attack() {
System.out.println(name + "가 활로 화살을 쐈습니다!");
}
}
//마법사
class Mage extends Character {
Mage(String name, int level) {
super(name, level);
}
void attack() {
System.out.println(name + "가 마법을 발사했습니다!");
}
}
각 자식클래스에서는 추상클래스의 공통 필드 및 메서드를 지니며 , 클래스마다 다르게 구현해야하는 attack은 자식 클래스에서 재정의함.
여기서 알아볼 수 있는 점은, 추상클래스는 기능구현에 목적을 둔다기보다 클래스의 상속에 더 무게를 두고 잇음을 알 수 있음.
2. 인터페이스 사용 케이스
만약 캐릭터들마다 다른 방식으로 사용 가능한 특수 스킬 같은게 존재한다면, 이는 인터페이스를 통해 구현한다.
interface SkillUser {
void useSkill(); // 스킬 사용 기능 (구체적인 내용은 없음)
}
class Warrior implements SkillUser {
public void useSkill() {
System.out.println("검사가 강력한 베기를 사용합니다!");
}
}
class Archer implements SkillUser {
public void useSkill() {
System.out.println("궁수가 정밀 사격을 합니다!");
}
}
class Mage implements SkillUser {
public void useSkill() {
System.out.println("마법사가 불꽃 마법을 사용합니다!");
}
}
만약 이러한 특별 스킬의 종류가 다양하고, 하나의 캐릭터가 여러개의 특별스킬을 가져야 하는 경우에도 인터페이스를 통해 구현한다.
interface SkillUser {
void useSkill(); // 스킬 사용 기능 (구체적인 내용은 없음)
}
interface SuperSkillUser{
void superSkill();
}
class Warrior implements SkillUser , SuperSkillUser {
public void useSkill() {
System.out.println("검사가 강력한 베기를 사용합니다!");
}
public void superSkill() {
System.out.println("검사가 돌려차기를 사용합니다!");
}
}
class Archer implements SkillUser {
public void useSkill() {
System.out.println("궁수가 정밀 사격을 합니다!");
}
}
class Mage implements SkillUser {
public void useSkill() {
System.out.println("마법사가 불꽃 마법을 사용합니다!");
}
}
위 인터페이스 사용예시를 살펴보면 인터페이스는 클래스가 가져야할 공통 속성 정의보다는 생성해야할 기능 구현에 초점을 맞춰 구현된 것을 확인할 수 있다. 즉 인터페이스를 클래스에 추가하는 행위는 인터페이스의 추상메서드를 반드시 구현해야해 라는 약속을 추가하는 행위라고 볼 수 있다.
5. 요약 정리
추상 클래스:
"공통 기능" + "일부 강제 구현"
약간의 구현 내용을 포함할 수 있음.
클래스의 상속과 특정 기능의 강제 구현을 요구할때 사용
인터페이스:
"100% 약속"
기능 명세만 선언하고, 구현은 구현체에게 맡김.
기능의 강제 구현을 위해 사용
Last updated