Fast Blinking Hello Kitty
 

[📖JAVA] 자바 상속 개념, 인터페이스 추상클래스 차이➰(is a / has a / Can do 관계)

13.png

1️⃣ 상속

✔️ 상속 키워드: extends
상속은 하나의 클래스가 다른 클래스의 속성과 메소드를 물려받아 사용하는 개념입니다.

 

2️⃣ 인터페이스

인터페이스는 클래스가 반드시 구현해야 하는 메서드의 목록을 정의하는 일종의 계약입니다.
 메서드의 시그니처만 정의하고, 메서드의 구현은 포함하지 않습니다.

인터페이스에서는 전부 추상이기 때문에 메소드를 생성할 때

 abstract 키워드를 명시하지 않아도 기본적으로 추상 메소드로 처리됩니다.

 

✔️ 상속 키워드: impleaments

public interface Animal {
    void sound(); // 추상 메소드 (기본적으로 추상적)

    // abstract 키워드를 명시하지 않아도 추상 메소드로 처리됨
    abstract void move(); 
}

 

3️⃣ 추상 클래스

⭐ 추상 메서드가 하나라도 있는 클래스는 무조건 추상 클래스로 선언해야 한다.(인터페이스 제외)

상속을 목적으로 사용 되는 클래스

⭐ 추상 메서드는 상속 받는 자식 클래스가 반드시 오버라이딩해서 사용해야 한다.

 

✔️ 상속 키워드: extends

abstract class Animal { // 추상 클래스
	public abstract void sound(); // 추상 메소드(abstract 키워드 생략 불가)
}


추상 클래스는 완전하게 구현되지 않은 메서드(추상 메서드)를 포함할 수 있는 클래스입니다.

즉, 다른 클래스가 상속받아 사용하도록 만들어집니다.

추상 클래스는 일반 메서드와 필드도 가질 수 있으며, 이들 메서드는 구현이 되어 있어도 됩니다.


💬 동물이라는 추상 클래스가 있을 때, 고양이와 강아지는 동물을 상속받아 구체적인 동작을 구현할 수 있습니다.

4️⃣ Is-a / Has-a / Can-do 관계란?

◾ Is-a 관계(추상 클래스, 일반 클래스 사용)
동물과 개, 사각형과 정사각형 -> 상속의 개념

◾ Has-a 관계(한 클래스가 다른 클래스의 인스턴스를 멤버 변수로 포함)
자동차와 엔진, 도서관과 책 -> 가지다의 개념

 

◾ Can-do 관계(인터페이스 사용)

동물과 소리내기 -> 특정 행동의 개념

 

💡 인터페이스는 일반적으로 can-do 관계를 표현하지만

정의한 추상 메소드를 구현하면 구현한 (특정) 기능을 갖고 있을 수 있기 때문에 has-a 관계도 될 수 있습니다.

 

아래 예제를 통해 조금 더 자세히 살펴보겠습니다.

 

📎 인터페이스 has-a 관계 예제

/* 인터페이스 정의 */
public interface Animal {
    void sound();
}

/* 인터페이스를 구현하는 클래스 정의 */
public class Dog implements Animal {
    @Override
    public void sound() {
        System.out.println("멍멍");
    }
}

public class Cat implements Animal {
    @Override
    public void sound() {
        System.out.println("야옹");
    }
}

/* 인터페이스를 멤버 변수로 포함하는 클래스 정의 */
public class Zoo { 
    private Animal animal; // Animal 타입의 멤버 변수를 사용하여 Zoo는 Animal을 포함하는 has-a 관계를 가집니다.

    public Zoo(Animal animal) {
        this.animal = animal; // 생성자에서 Animal 객체를 초기화합니다.
    }

    public void letAnimalMakeSound() {
        animal.sound(); // Animal 객체의 sound 메소드를 호출하여 소리를 냅니다.
    }
}

/* has-a 관계를 사용하는 클래스 정의 */
public class Main {
    public static void main(String[] args) {
        Animal dog = new Dog();
        Animal cat = new Cat();

        Zoo dogZoo = new Zoo(dog); 
        Zoo catZoo = new Zoo(cat); 

        dogZoo.makeAnimalSound(); 
        catZoo.makeAnimalSound();
    }
}

 

Animal 인터페이스를 직접 객체로 만들 수 없기 때문에,

Zoo 클래스를 사용하여 Animal 객체를 포함하는 구조를 만든 것입니다.

이 구조를 통해 Animal 객체를 사용하는 방식으로 소리를 출력할 수 있습니다.

4️⃣ 추상클래스 vs 인터페이스 비교

✅ 구현 방식

특징 추상 클래스 인터페이스
필드 O (일반 필드 및 상수 필드 모두 가능) X (상수만 정의 가능, 모든 필드는 자동으로 public static final)
생성자 O (생성자 정의 가능) X (생성자 정의 불가)
일반 메소드 O (정상 메소드 정의 가능) 일부 가능 (default 메소드, static 메소드, private 메소드)
추상 메소드 O (추상 메소드 정의 가능) O (추상 메소드 정의 가능, 모든 메소드는 기본적으로 추상 메소드)
다중 상속 불가능 O (다중 구현/상속 가능)

 

💬 인터페이스에서 디폴트 메소드를 사용하는 이유?
인터페이스에 새로운 메소드를 추가하면서 기존 구현체에 영향을 미치지 않기 위해서이다.


📎인터페이스 can-do 관계와 예제

동물과 소리내기는 Can-do 관계라고 볼 수 있는데요.

Can-do 관계는 객체가 특정 행동이나 기능을 수행할 수 있음을 나타냅니다.

이를 상속이나 인터페이스의 개념으로 표현할 수 있는데

개인적으로 인터페이스로 나타내는게 적합한 것 같다는 생각이 들었습니다.

 

public interface Animal {
    void sound();
}

public class Cat implements Animal{
    public void sound(){
        System.out.println("야옹");
    }
}

public class Caw implements Animal {
    public void sound(){
        System.out.println("음매");
    }
}

public class Dog implements Animal {
    public void sound(){
        System.out.println("멍멍");
    }
}

public class AnimalSoundMain {
    public static void main(String[] args) {
        Animal dog = new Dog();
        Animal cat = new Cat();
        Animal caw = new Caw();

        System.out.println("동물 소리 테스트 시작");
        dog.sound();
        cat.sound();
        caw.sound();
        System.out.println("동물 소리 테스트 종료");

    }
}

 

위 예제를 살펴보면 인터페이스에 정의한 메소드들은 다른 클래스에 무조건적으로 그 메소드를 구현해야된다는 것을 볼 수 있는데요. 반면 추상클래스는 무조건적으로 작성하지 않아도 됩니다. 따라서 인터페이스가 조금 더 강한 느낌을 가지고 있습니다. 마치 계약과 같은 존재이죠.

728x90
320x100