인터페이스와 추상클래스의 차이점

V_브이_v·2024년 12월 6일
2

자바스터디

목록 보기
4/4
post-thumbnail

1. 추상클래스를 사용하면 되지, 왜 인터페이스를 사용하는 걸까요?

  • 추상 클래스와 인터페이스는 둘 다 추상적 개념을 정의하지만, 그 목적과 사용 방식이 다릅니다.
구분추상 클래스인터페이스
구현 가능 여부일부 메소드는 구현 가능모든 메소드 구현 불가능
다중 상속 여부단일 상속만 가능다중 구현 가능
필드멤버 변수, 상수 모두 가능상수만 가능
사용 목적공통기능의 일부 구현 제공규약 제공 및 구현 강제

추상 클래스와 인터페이스의 사용 기준

추상 클래스 사용 시점

  • “is-a” 관계를 표현할 때 사용합니다.
  • 예를 들어, “자동차(Car)는 차량(Vehicle)이다”처럼 상속 관계를 명확히 정의할 때 적합합니다.
  • 기본적으로 공통된 기능상태(멤버 변수)를 제공하고, 이를 상속받아 구체적으로 확장하고자 할 때 사용합니다.
  • 부분적으로 구현된 클래스가 필요할 때 사용합니다.
  • 추상 메서드(구현 필요)와 구현된 메서드(공통 로직 제공)를 함께 포함할 수 있습니다.

인터페이스 사용 시점

  • “can-do” 관계를 표현할 때 사용합니다.
  • 예를 들어, “비행기는 날 수 있다(Flyable)“처럼 특정 동작을 강제하고 싶을 때 적합합니다.
  • 클래스 간에 공통 동작의 규약을 정의할 때 사용합니다.
  • 다중 구현이 필요할 때 사용합니다.
  • 여러 동작을 결합해야 하는 상황에서 유용합니다.

2. 예제를 통한 설명

추상 클래스 예제: 공통 상태와 기능이 있는 경우

상황: 동물(Animal)
모든 동물은 이름소리라는 공통 속성이 있으며, 대부분 걷거나 특정 이동 방식을 가지고 있습니다.
이러한 공통된 상태와 동작은 추상 클래스로 구현하기 적합합니다.

추상클래스

abstract class Animal {
    String name;

    Animal(String name) {
        this.name = name;
    }

    void sleep() { // 공통 동작
        System.out.println(name + " is sleeping.");
    }

    abstract void move(); // 구체적인 이동 방식은 하위 클래스가 정의
}

구현

class Dog extends Animal {
    Dog(String name) {
        super(name);
    }

    @Override
    void move() {
        System.out.println(name + " runs on four legs.");
    }
}

class Bird extends Animal {
    Bird(String name) {
        super(name);
    }

    @Override
    void move() {
        System.out.println(name + " flies in the sky.");
    }
}

사용

public class Main {
    public static void main(String[] args) {
        Animal dog = new Dog("Rover");
        Animal bird = new Bird("Tweety");

        dog.move();  // 출력: Rover runs on four legs.
        bird.move(); // 출력: Tweety flies in the sky.
        dog.sleep(); // 출력: Rover is sleeping.
    }
}

인터페이스 예제: 동작을 강제해야 하는 경우

상황: 특정 행동

동물들이 특정 행동(예: 날기, 수영하기)을 할 수 있는지를 명시하려면 인터페이스를 사용합니다.
이 행동은 동물 외에도 예를 들어, 로봇이나 장난감에도 적용될 수 있습니다.

인터페이스

interface Flyable {
    void fly();
}

interface Swimmable {
    void swim();
}

구현

class Duck extends Animal implements Flyable, Swimmable {
    Duck(String name) {
        super(name);
    }

    @Override
    void move() {
        System.out.println(name + " waddles on the ground.");
    }

    @Override
    public void fly() {
        System.out.println(name + " flies a short distance.");
    }

    @Override
    public void swim() {
        System.out.println(name + " swims in the pond.");
    }
}

class Fish extends Animal implements Swimmable {
    Fish(String name) {
        super(name);
    }

    @Override
    void move() {
        System.out.println(name + " swims in the water.");
    }

    @Override
    public void swim() {
        System.out.println(name + " is swimming.");
    }
}

사용

public class Main {
    public static void main(String[] args) {
        Duck duck = new Duck("Donald");
        Fish fish = new Fish("Nemo");

        duck.fly();   // 출력: Donald flies a short distance.
        duck.swim();  // 출력: Donald swims in the pond.
        duck.move();  // 출력: Donald waddles on the ground.

        fish.swim();  // 출력: Nemo is swimming.
        fish.move();  // 출력: Nemo swims in the water.
    }
}

정리: 추상 클래스와 인터페이스의 역할 비교

추상 클래스:

  • 공통 속성(name)과 동작(sleep)을 제공.
  • 공통된 부모 역할을 하며, 상태와 기능을 상속받아 구체적으로 확장.

인터페이스:

  • 특정 동작(fly, swim)을 강제.
  • 동작이 필요하지만 공통 속성과는 무관한 경우 사용.
  • 다중 구현 가능.

선택 기준

1) 공통된 속성/기능이 필요한 경우:

  • 추상 클래스를 사용.
  • 예: 동물, 차량 등 공통된 특성과 일부 동작을 공유하는 경우.
    2) 특정 행동을 강제하고 싶은 경우:
  • 인터페이스를 사용.
  • 예: 날기(Flyable), 수영하기(Swimmable), 걷기(Walkable) 등.
    3) 둘을 함께 사용:
  • 추상 클래스는 공통 상태와 기본 동작을 제공하고, 인터페이스는 특정 행동을 추가적으로 강제할 수 있습니다.
  • 예: 위의 Duck처럼 Animal을 상속받으면서 Flyable, Swimmable 인터페이스를 구현.
profile
지속가능한 사회적 가치의 현실화

0개의 댓글