부모 클래스, 상속, super

moon.kick·2025년 2월 24일

코드

package ex0224.superkeyword;

// 부모 클래스: Animal
class Animal {
    int age = 5;
    String bodyColor; // 기본값 null

    public void sound() {
        System.out.println("super sound call");
    }

    public void eat() {
        System.out.println("super eat call");
    }
}

// 자식 클래스: Cat
class Cat extends Animal {
    int age = 2; // 부모 클래스와 동일한 변수 선언 (Shadowing)
    int weight;  // Cat 클래스만의 추가 필드

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

    public void run() {
        System.out.println("잘 달린다");
    }

    public void test() {
        System.out.println("======= 필드 값 확인 =======");
        System.out.println("age (Cat) : " + age);
        System.out.println("this.age (Cat) : " + this.age);
        System.out.println("super.age (Animal) : " + super.age);

        System.out.println("---------------------------");
        System.out.println("bodyColor (Animal) : " + bodyColor);
        System.out.println("this.bodyColor (Animal) : " + this.bodyColor);
        System.out.println("super.bodyColor (Animal) : " + super.bodyColor);

        System.out.println("---------------------------");
        System.out.println("weight (Cat) : " + weight);
        System.out.println("this.weight (Cat) : " + this.weight);
        // System.out.println(super.weight); // 부모 클래스에 존재하지 않음 (컴파일 오류)

        System.out.println("======= 메서드 호출 =======");
        System.out.println("[sound()]");
        sound();
        this.sound();
        super.sound();

        System.out.println("[eat()]");
        eat();
        this.eat();
        super.eat();

        System.out.println("[run()]");
        run();
        this.run();
        // super.run(); // 부모 클래스에 없는 메서드 (컴파일 오류)
    }
}

// 실행 클래스
public class SuperKeywordExam {
    public static void main(String[] args) {
        System.out.println("======= Cat 객체 생성 및 호출 =======");
        Cat cat = new Cat();
        System.out.println("cat.age : " + cat.age);
        System.out.println("cat.bodyColor : " + cat.bodyColor);
        System.out.println("cat.weight : " + cat.weight);

        cat.sound();
        cat.eat();
        cat.run();

        System.out.println("==============================");
        System.out.println("======= 업캐스팅 후 호출 =======");

        Animal animal = new Cat();
        System.out.println("animal.age : " + animal.age);
        System.out.println("animal.bodyColor : " + animal.bodyColor);
        // System.out.println(animal.weight); // 부모 클래스에 없는 필드 (컴파일 오류)

        animal.sound(); // Cat 클래스의 오버라이딩된 메서드 실행
        animal.eat();
        // animal.run(); // Animal 타입으로는 Cat의 메서드 호출 불가 (컴파일 오류)

        System.out.println("animal 주소 = " + animal);

        // 다운캐스팅: 부모 타입 → 자식 타입
        if (animal instanceof Cat) { // 안전한 캐스팅 확인
            Cat c = (Cat) animal;
            System.out.println("c 주소 = " + c);
            System.out.println("c.weight : " + c.weight);
            c.run(); // Cat 클래스의 run() 호출 가능
        }
    }
}

🔹 변경 및 개선 사항

  1. 가독성 개선

    • 코드 간격 정리 및 주석 정리.
    • System.out.println()에 필드명과 클래스명을 명확히 표기.
  2. 불필요한 코드 제거

    • super.weight는 부모 클래스에 없기 때문에 주석 처리.
    • super.run()도 부모 클래스에 없어서 주석 처리.
  3. 출력 가독성 향상

    • ======= 구분선 =======을 추가하여 실행 흐름이 명확하게 보이도록 함.
    • System.out.println("메서드 호출") 구분하여 출력.

이제 코드가 깔끔하고 구조적으로 정리되어 가독성이 좋아졌어요! 🚀

📌 Java 상속과 super 키워드 정리

1. 상속(Inheritance) 개념

  • Cat 클래스는 Animal 클래스를 상속받음 (extends Animal).
  • 상속을 통해 부모(Animal)의 속성과 메서드를 자식(Cat)이 물려받음.
  • 부모 클래스의 필드와 메서드를 자식 클래스에서 사용할 수 있음.
  • 자식 클래스는 부모 클래스의 메서드를 재정의(오버라이딩, @Override) 할 수 있음.

2. super 키워드 사용

  • super 키워드는 부모 클래스(Animal)의 멤버(필드, 메서드)를 참조할 때 사용.
  • 필드 접근
    • super.age → 부모 클래스의 age 값 참조 (5)
    • this.age → 자식 클래스의 age 값 참조 (2)
  • 메서드 호출
    • super.sound() → 부모 클래스의 sound() 실행 (super sound call)
    • this.sound() 또는 sound() → 자식 클래스의 sound() 실행 (야옹)
  • 주의할 점
    • 부모 클래스에 없는 자식 클래스의 필드는 super로 접근할 수 없음.
    • 예: super.weight는 부모 클래스(Animal)에 존재하지 않으므로 접근 불가.

3. super 키워드 사용 예제 (출력 정리)

System.out.println(age);      // 2 (자식 클래스 Cat의 age)
System.out.println(this.age); // 2 (this는 현재 객체의 age)
System.out.println(super.age);// 5 (부모 클래스 Animal의 age)

System.out.println(bodyColor);      // null (부모로부터 상속됨)
System.out.println(this.bodyColor); // null
System.out.println(super.bodyColor);// null

System.out.println(weight);      // 0 (자식 클래스 Cat의 필드)
System.out.println(this.weight); // 0
// System.out.println(super.weight); // 오류! 부모에는 weight 필드 없음

System.out.println("=======메서드 호출==========");
sound();          // "야옹" (자식 클래스의 메서드)
this.sound();     // "야옹"
super.sound();    // "super sound call" (부모 클래스의 메서드)

System.out.println("=======메서드 호출==========");
eat();          // "super eat call" (부모의 메서드를 오버라이딩하지 않음)
this.eat();     // "super eat call"
super.eat();    // "super eat call"

System.out.println("=======메서드 호출==========");
run();          // "잘달린다" (자식 클래스의 메서드)
this.run();     // "잘달린다"
// super.run(); // 오류! 부모 클래스에 run() 없음

4. 업캐스팅과 다운캐스팅

  • Animal animal = new Cat();업캐스팅 (Upcasting)
    • 부모 타입(Animal) 참조 변수로 자식 객체(Cat)를 가리킴.
    • 이때 부모 클래스의 필드 값이 사용됨 (age = 5).
    • 메서드는 자식 클래스에서 오버라이딩된 메서드가 실행됨 (sound()는 "야옹").
    • 하지만 run() 같은 자식 클래스 전용 메서드는 호출 불가.
Animal animal = new Cat();
System.out.println(animal.age);         // 5 (부모 클래스의 필드)
System.out.println(animal.bodyColor);   // null (부모 클래스에서 상속된 필드)
animal.sound(); // "야옹" (오버라이딩된 메서드 실행)
animal.eat();   // "super eat call"
// animal.run(); // 오류! Animal 타입으로는 Cat의 메서드 호출 불가
  • 다운캐스팅 (Downcasting)
    • 업캐스팅된 객체를 다시 원래의 자식 타입(Cat)으로 변환.
    • if (animal instanceof Cat)으로 안전성 확인 후 변환.
if(animal instanceof Cat) { 
    Cat c = (Cat) animal;  // 다운캐스팅
    System.out.println(c.weight); // 0 (자식 클래스의 필드 접근 가능)
    c.run(); // "잘달린다" (자식 클래스의 메서드 호출 가능)
}
  • instanceof를 사용하지 않으면 ClassCastException 발생할 가능성이 있음.

📌 핵심 정리

super 키워드

  • 부모 클래스의 필드 및 메서드를 호출할 때 사용.
  • super.age → 부모 클래스 age 값.
  • super.sound() → 부모 클래스의 sound() 실행.

메서드 오버라이딩

  • 부모 클래스의 메서드를 자식 클래스에서 재정의.
  • 오버라이딩된 메서드는 부모 타입으로 접근해도 자식 클래스의 메서드가 실행됨.

업캐스팅 (Upcasting)

  • Animal animal = new Cat();
  • 부모 타입 변수로 자식 객체를 가리킬 수 있음.
  • 부모 클래스의 필드만 접근 가능하지만, 오버라이딩된 메서드는 자식 클래스의 것이 실행됨.

다운캐스팅 (Downcasting)

  • if (animal instanceof Cat) { Cat c = (Cat) animal; }
  • 부모 타입으로 업캐스팅된 객체를 다시 원래의 자식 타입으로 변환.
  • 다운캐스팅 후에는 자식 클래스의 필드와 메서드를 사용할 수 있음.

💡 상속을 통해 코드의 재사용성을 높이고, super와 업캐스팅/다운캐스팅을 활용하여 객체지향적인 설계를 할 수 있음! 🚀

profile
@mgkick

0개의 댓글