_

Always be tactful

프로그래밍/배웠어, 자바

[Java] super 키워드 / 상속과 메모리 구조

funczun 2025. 1. 23. 01:23

 자바는 단일 상속만 가능하며, 상속받고자 하는 클래스에 extends 키워드를 사용하면 된다. 아래 예제에서는 Animal 클래스를 Dog와 Cat이 상속받아 기존의 코드를 재사용한다.

// 부모 클래스
public class Animal {

    public void eat() {
        System.out.println("Eat!");
    }
}
// 자식 클래스
public class Dog extends Animal {

    public void bark() {
        System.out.println("bark!");
    }
}
// 자식 클래스
public class Cat extends Animal {

    public void meow() {
        System.out.println("Meow!");
    }
}

다이아몬드 문제
  A
 / \
B   C
 \ /
  D

 

 이러한 구조에서 D는 B와 C를 통해 A의 메서드를 두 번 상속받게 된다. 따라서 A의 메서드가 두 번 호출되거나, 서로 다른 버전의 메서드를 참조해 문제를 일으킬 수 있다. 이렇듯 클래스 상속과 인터페이스 구현에서 발생할 수 있는 문제를 '다이아몬드 문제'라고 하며, 자바에서는 이를 막기 위해 단일 상속만을 지원한다고 이해하면 된다.


 참고로 자바에서 상속이란, 단순하게 부모의 필드와 메서드만 물려받는 게 아니다. 메모리 구조상 부모 클래스도 함께 포함해서 생성된다. 외부적으로는 하나의 인스턴스를 생성하는 것 같지만 내부에서는 부모 클래스와 자식 클래스 모두 생성되고 공간도 구분된다는 뜻이다.

*필드: 속성

*인스턴스: 객체

메서드 호출 시 작동 방식


@Override

 자바에서 @는 애노테이션을 나타내는 데 사용된다. 애노테이션이란 메타데이터의 일종으로, 주로 클래스/메서드/필드 등에 추가하여 해당 코드에 대한 정보를 제공하거나 특정 동작을 수행하도록 돕는다. 프로그램이 읽을 수 있는 특별한 주석으로 이해하면 쉽다.

public class Cat extends Animal {

    public void meow() {
        System.out.println("Meow!");
    }

    // 오버라이딩
    @Override
    public void eat() {
        System.out.println("Eat in a cute way!");
    }
}

 

 본 예제에서는 고양이에 대한 사심을 담아 상위 클래스의 eat() 메서드를 특별하게 오버라이드해주었다. 사실 @Override 표시를 무조건 해주어야 하는 건 아니지만, 컴파일러는 이 애노테이션을 보아야 메서드가 정확히 오버라이드 되었는지 확인하기 때문에 웬만하면 붙이는 게 낫다.


*오버 로딩: 메서드 이름이 같고 파라미터가 다른 메서드 여러개를 정의하는 것

*오버 라이딩: 하위 클래스에서 상위 클래스의 메서드를 재정의하는 것


super
public class Cat extends Animal {

    public void meow() {
        System.out.println("Meow!");
    }

    // 오버라이딩
    @Override
    public void eat() {
        System.out.println("Eat in a cute way!");
    }
    
    // 부모 메서드 호출
    public void call() {
        super.eat(); // super
    }
}

 

 구조상, 메서드를 본인 타입에서 이미 찾은 경우, 부모 클래스까지 가지 않아 부모 메서드를 호출할 수 없게 된다. 하지만 super 키워드를 사용하면 부모 메서드를 직접 호출할 수 있다. (*생성자의 경우 무조건 super가 한 번은 포함되어야 한다.)

728x90