Java (상속 extends)

최병현·2026년 1월 6일

java

목록 보기
26/38

상속(Inheritance) 정리

상속은 객체 지향 프로그래밍(OOP)의 핵심 개념 중 하나로, 기존 클래스(부모/슈퍼 클래스)의 field와 method를 재사용해서 새로운 클래스(자식/서브 클래스)를 만드는 방식이다. 즉, “공통 기능은 위에 모으고”, “개별 기능은 아래에서 확장”하는 구조로 코드를 설계한다.


1. 상속이 필요한 이유

상속을 쓰면 여러 클래스에 반복되는 코드를 부모 클래스에 모아두고, 자식 클래스들이 재사용할 수 있다.

예를 들어 Animal(동물)에 공통 속성(이름, 나이)과 공통 행동(move)을 정의해두면, Dog/Cat/Human/Tiger 같은 자식 클래스는 자신만의 고유 기능만 추가하면 된다.

결과적으로 코드 중복을 줄이고 유지보수도 쉬워진다.


2. 상속의 특징

1) 단일 상속: Java는 한 번에 하나의 부모 클래스만 상속 가능하다.
2) super: 부모의 생성자/field/method 접근에 사용한다.
3) method override: 자식이 부모의 기능을 “재정의”할 수 있다.
4) final class: 클래스에 final이 붙으면 상속 불가.
5) final method: 메서드에 final이 붙으면 override 불가.


3. IS-A 관계

상속은 “IS-A 관계”를 표현한다. 예: Tiger is an Animal, Human is an Animal 부모는 더 일반적이고 넓은 범위, 자식은 더 구체적이고 특징이 있는 존재로 설계한다.


4. super 키워드 정리

super() : 부모 클래스의 생성자를 호출
super.method() : 부모 클래스의 메서드를 호출


5. 예제 코드

아래 코드는 Animal(부모)을 기준으로 Human/Tiger(자식)가 상속받아 확장하는 구조를 보여준다.

import java.util.Arrays;

/*
    Backend/OOP logic in Java: Inheritance + Override + super usage
*/

class Animal {
    private String animalName;
    private int animalAge;

    public Animal() {}

    public Animal(String animalName) {
        this.animalName = animalName;
    }

    public Animal(int animalAge) {
        this.animalAge = animalAge;
    }

    public Animal(String animalName, int animalAge) {
        this.animalName = animalName;
        this.animalAge = animalAge;
    }

    public String getAnimalName() {
        return animalName;
    }

    public void setAnimalName(String animalName) {
        this.animalName = animalName;
    }

    public int getAnimalAge() {
        return animalAge;
    }

    public void setAnimalAge(int animalAge) {
        this.animalAge = animalAge;
    }

    public void move() {
        System.out.println("움직입니다.");
    }
}

class Human extends Animal {

    public Human() {
        System.out.println("사람 객체가 생성되었습니다.");
    }

    @Override
    public void move() {
        System.out.println("사람이 두 발로 걷습니다.");
    }

    public void read(String book) {
        System.out.println(getAnimalName() + "이 " + book + "를 읽는 중입니다.");
    }
}

class Tiger extends Animal {
    private double weight;

    public Tiger() {}

    public Tiger(String animalName, int animalAge, double weight) {
        super(animalName, animalAge); // super() to call parent constructor
        this.weight = weight;
    }

    public double getWeight() {
        return weight;
    }

    public void setWeight(double weight) {
        this.weight = weight;
    }

    public void hunt() {
        System.out.println(getAnimalName() + "(이)가 사냥을 합니다.");
    }

    public void hunt(String prey) { // overload
        System.out.println(getAnimalName() + "(이)가 " + prey + "을(를) 사냥합니다.");
    }

    @Override
    public void move() {
        System.out.print("호랑이가 ");
        super.move(); // call parent method
    }
}

public class Main {
    public static void main(String[] args) {

        Animal animal1 = new Animal();
        animal1.move();
        animal1.setAnimalName("동물");
        animal1.setAnimalAge(12);

        Tiger tiger1 = new Tiger();
        tiger1.setAnimalName("호랑이");
        tiger1.setAnimalAge(1);

        System.out.println("이 호랑이의 이름은 " + tiger1.getAnimalName()
                + "이고, 나이는 " + tiger1.getAnimalAge() + "살 입니다.");

        tiger1.move();
        tiger1.hunt();
        tiger1.hunt("사료");

        tiger1.setWeight(1.4);
        System.out.println(tiger1.getAnimalName() + "의 몸무게는 " + tiger1.getWeight() + "t 입니다.");

        System.out.println("------------------------------------------------");

        Human human1 = new Human();
        human1.move();
        human1.setAnimalName("여러분이름");
        human1.setAnimalAge(35);

        System.out.println("안녕하세요, 제 이름은 " + human1.getAnimalName()
                + "이고 나이는 " + human1.getAnimalAge() + "살입니다."
                + "\n내년에는 " + (human1.getAnimalAge() + 1) + "살이 됩니다.");

        human1.read("자바의 기초");
    }
}

6. 추가 활용 및 제약 사항

- 부모 클래스는 자식 클래스의 고유 메서드를 호출할 수 없다. (예: Animal 타입 변수로 hunt() 호출 불가)
- override는 “부모가 가진 메서드”를 “자식이 같은 시그니처로 재정의”하는 것이다.
- super.move()처럼 부모 동작을 일부 재사용하면서 자식 동작을 덧붙이는 패턴이 자주 나온다.
- final은 상속/오버라이딩을 막아 설계를 고정할 때 사용한다.


7. 정리

상속은 공통 코드를 부모에 모으고, 자식이 이를 재사용/확장하는 구조다. 중복을 줄이고 유지보수를 쉽게 해주며, IS-A 관계를 코드로 표현할 수 있다. 단, 단일 상속만 가능하고(final 포함) override 규칙을 정확히 이해한 상태에서 사용하는 것이 중요하다.

profile
Develop

0개의 댓글