티스토리 뷰

자바

자바의 상속과 오버라이딩 완전 정리

박완희버서커 2025. 7. 14. 15:35
반응형
자바의 상속과 오버라이딩 완전 정리

🔷 자바의 상속과 오버라이딩 완전 정리


✅ 상속이란?

상속이란 부모 클래스가 정의한 변수와 메서드를 자식 클래스가 물려받아 그대로 사용할 수 있게 하는 기능입니다.
객체지향 프로그래밍에서 코드 재사용성을 높이고, 공통 기능을 한 곳에서 관리해 유지보수를 쉽게 할 수 있는 핵심적인 요소입니다.
자식 클래스는 부모의 기능을 그대로 사용하거나, 필요에 따라 수정하거나 새로운 기능을 추가할 수 있습니다.


예를 들어 Animal이라는 부모 클래스가 sound()라는 메서드를 가지고 있다면, Dog라는 자식 클래스는 sound()를 그대로 사용하거나 자신만의 방식으로 다시 정의할 수 있습니다.


✅ 오버라이딩이란?

정의

오버라이딩(Overriding)은 부모 클래스에 정의된 메서드를 자식 클래스에서 같은 이름, 같은 매개변수로 다시 정의하는 것(덮어쓰기)입니다.
상속만 하면 부모의 기능이 그대로 실행되지만, 오버라이딩을 하면 자식의 상황에 맞게 동작을 바꿀 수 있습니다.


왜 필요한가?

오버라이딩은 단순히 “부모의 동작을 자식에 맞게 바꾼다”는 추상적인 설명으로는 부족합니다.
현실적인 프로그래밍 상황에서 다음과 같은 이유로 꼭 필요합니다.

  • 부모의 기본 동작이 자식의 상황과 맞지 않을 때
    → 예: 부모는 모든 동물이 같은 소리를 낸다고 정의했지만, 자식마다 소리가 달라 Dog는 짖고 Cat은 야옹해야 할 때
  • 공통된 메서드 이름을 유지하면서 다른 동작을 하고 싶을 때
    → 예: 리스트에 담긴 여러 동물 객체를 반복문으로 돌리며 sound()를 호출하면 각 동물이 자신만의 소리를 내도록 하고 싶을 때
  • 부모가 제공하는 기본 구현을 개선하거나 기능을 확장하고 싶을 때
    → 예: 부모의 log()는 메시지 출력만 하지만, 자식에서는 시간까지 같이 출력하고 싶을 때
  • 프레임워크나 라이브러리에서 정해진 메서드를 반드시 구현해야 할 때
    → 예: 서블릿에서 doGet() 메서드를 구현해 GET 요청 처리 로직을 작성해야 할 때

이처럼 오버라이딩은 코드의 유연성과 확장성을 높이고, 공통된 인터페이스를 유지하면서도 각기 다른 동작을 구현할 수 있게 해줍니다.


✅ 오버라이딩 방법

@Override는 어디에 붙이는가?

@Override는 반드시 자식 클래스의 메서드에 붙입니다.
부모 클래스에 정의된 메서드를 자식 클래스에서 재정의할 때, 그 메서드 바로 위에 붙입니다.
부모 클래스에는 붙이지 않습니다. 왜냐하면 부모는 원본 메서드를 정의하는 클래스이기 때문입니다.


@Override를 붙이는가?

@Override는 없어도 프로그램은 실행됩니다. 하지만, 다음과 같은 이유로 반드시 붙이는 것이 좋습니다.

  • ✅ 부모에 정의된 메서드를 정확히 재정의하고 있는지 컴파일 시점에 검증합니다.
  • ✅ 부모에 없는 메서드에 잘못 붙이면 컴파일 단계에서 오류가 발생해 실수를 미리 발견할 수 있습니다.
  • ✅ 메서드 이름, 매개변수 등을 잘못 작성해도 오류 없이 동작하는 문제를 막고 버그를 예방합니다.
  • ✅ 코드의 의도를 명확하게 표현해, 다른 개발자가 코드를 읽을 때 “이 메서드는 부모의 것을 덮어쓰는 것이다”라는 점을 이해하기 쉽게 합니다.

@Override 없이 작성했을 때의 문제

코드

class Animal {
    public void sound() {
        System.out.println("동물이 소리를 냅니다.");
    }
}

class Dog extends Animal {
    public void Sound() {  // 대소문자 오타
        System.out.println("개가 짖습니다.");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.sound();
    }
}

출력

동물이 소리를 냅니다.

설명:

자식 클래스에서 메서드 이름을 잘못 작성했지만, 컴파일러는 이를 새로운 메서드로 인식하고 부모의 메서드를 그대로 실행합니다.
의도한 동작과 다른 결과가 나옵니다.


@Override를 붙였을 때

코드

class Animal {
    public void sound() {
        System.out.println("동물이 소리를 냅니다.");
    }
}

class Dog extends Animal {
    @Override
    public void Sound() {  // 대소문자 오타
        System.out.println("개가 짖습니다.");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.sound();
    }
}

컴파일 오류 메시지

error: method does not override or implement a method from a supertype

설명:

@Override 덕분에 부모에 존재하지 않는 메서드를 재정의하려 했다는 것을 컴파일 단계에서 감지합니다.
이렇게 해서 의도하지 않은 오류를 사전에 방지할 수 있습니다.


✅ 실행 예제: 올바른 오버라이딩

@Override 없이 올바르게 오버라이딩

코드

class Animal {
    public void sound() {
        System.out.println("동물이 소리를 냅니다.");
    }
}

class Dog extends Animal {
    public void sound() {
        System.out.println("개가 짖습니다.");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.sound();
    }
}

출력

개가 짖습니다.

@Override를 붙여 올바르게 오버라이딩

코드

class Animal {
    public void sound() {
        System.out.println("동물이 소리를 냅니다.");
    }
}

class Dog extends Animal {
    @Override
    public void sound() {
        System.out.println("개가 짖습니다.");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.sound();
    }
}

출력

개가 짖습니다.

설명:

@Override는 부모의 메서드를 정확히 재정의하고 있음을 확인하고, 실수를 방지하며 의도를 명확히 합니다.


✅ 부모에 메서드가 있고, 자식이 재정의를 하지 않은 경우

코드

class Animal {
    public void sound() {
        System.out.println("동물이 소리를 냅니다.");
    }
}

class Dog extends Animal {
    // 재정의하지 않음
}

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.sound();
    }
}

출력

동물이 소리를 냅니다.

설명:

자식 클래스가 부모의 메서드를 재정의하지 않으면, 부모의 메서드가 그대로 실행됩니다. 오류는 없습니다.


✅ 결론

  • 상속은 부모의 기능을 자식에게 물려주어 코드 재사용성을 높입니다.
  • 오버라이딩은 부모의 기능을 자식의 상황에 맞게 재정의할 수 있도록 해줍니다.
  • @Override는 자식 클래스의 메서드에 붙이며, 부모 메서드를 정확히 재정의하고 있는지를 컴파일 시점에 검증합니다.
  • @Override를 사용하면 실수를 방지하고, 코드의 의도를 명확히 표현할 수 있습니다.

✅ 요약표

구분 내용
상속 부모의 기능을 자식에 물려줌
오버라이딩 부모의 메서드를 자식에서 같은 시그니처로 재정의
@Override의 위치 자식 클래스의 메서드에 붙임
@Override의 장점 실수 방지, 시그니처 검증, 가독성, 유지보수 용이
부모에만 있고 자식에 없음 부모의 메서드가 그대로 실행

반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/10   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함
반응형