Java

상속이란?

한 클래스가 다른 클래스의 속성과 메서드를 물려받는 것

중복되는 속성과 메서드를 복사하여 코드의 재사용성을 높이고 유지 보수를 쉽게 함

extends 키워드를 사용 (예시 : class 자식클래스명 extends 부모클래스명)

instanceof 연산자로 상속 관계 확인 가능 (예시 : if(자식클래스명 instanceof 부모클래스명))

  • 상속하는 부모 클래스 = Super Class (Base Class) : 기존 속성과 메서드를 정의한 클래스
  • 상속받는 자식 클래스 = Sub Class (Derived Class) : 기존 속성과 메서드를 확장하여 새로운 기능을 추가하는 클래스

상속의 특징

  • is-a 관계임
  • Sub Class에서 Super Class에 없는 메서드나 인스턴스 변수를 추가할 수 있음 
  • Sub Class에서 Super Class의 속성과 메서드를 사용, 변경, 확장하여 사용할 수 있음
  • Sub Class에서 Super Class의 Private, Static, Final 메서드 또는 변수에 대해서는 접근 불가할 수 있음
  • 특히, Final class는 상속이 불가능하고 Final method는 오버라이딩이 불가능함
  • Super Class의 참조가 Sub Class가 되는 경우는 안전하지 않을 수 있음 (ILLEGAL)
  • Java에서 클래스의 다중 상속은 불가능하지만, 인터페이스(Interfaces)의 다중 상속은 가능함
  • Java의 많은 메서드들은 Object class에서 상속 받은 것임
// Super Class
class Animal {
    String name;

    void eat() {
        System.out.println(name + " is eating food.");
    }
}

// Sub Class (Animal 클래스를 상속)
class Dog extends Animal { // extends로 상속
    void bark() {
        System.out.println(name + " is barking.");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog myDog = new Dog();
        myDog.name = "Poppi";  // Super Class의 필드 사용
        myDog.eat();  // Super Class의 메서드 사용
        myDog.bark(); // Sub Class의 메서드 사용
    }
}

 

매서드 오버라이딩 / Method Overriding

부모 클래스의 메서드를 자식 클래스에서 재정의하여 다르게 동작하게 할 수 있음

@Override 어노테이션을 사용하여 오버라이딩을 명확히 표시

※ 오버로딩(Overloading)과는 다르다 (여기를 참조)

class Animal {
    void makeSound() {
        System.out.println("Animal makes sounds.");
    }
}

class Dog extends Animal {
    @Override  // 어노테이션으로 명시
    void makeSound() {  // 부모 클래스의 메서드를 재정의
        System.out.println("Bow-wow!");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal myAnimal = new Animal();
        myAnimal.makeSound();  // "Animals make sounds."

        Dog myDog = new Dog();
        myDog.makeSound();  // "Bow-wow!" (오버라이딩된 메서드 실행)
    }
}

업캐스팅 & 다운캐스팅 (Upcasting & Downcasting)

상속 관계에서 객체 간 타입 변환이 가능함

  • 업캐스팅 (Upcasting)
    • 자식 클래스 → 부모 클래스
    • 컴파일러에서 자동으로 변환
    • 부모 클래스 타입의 참조 변수로 자식 클래스의 객체를 참조
    • 자식 클래스의 메서드를 부모 클래스 타입으로 호출 가능
    • 하지만, 자식 클래스에만 있는 멤버(필드, 메서드)에는 접근 불가능
    • 오버라이딩된 메서드는 자식 클래스의 메서드를 따름
  • 다운캐스팅 (Downcasting)
    • 부모 클래스 → 자식 클래스
    • 부모 타입을 다시 자식 타입으로 변환
    • 명시적 변환 필요 (자식 클래스명 괄호)
    • 부모 클래스에서 선언되지 않은 자식의 멤버(필드, 메서드)에 접근 가능
    • 잘못된 다운캐스팅은 ClassCastException 발생 가능
    • instanceof 연산자를 사용하여 변환이 안전한지 확인
class Animal {
    void makeSound() {
        System.out.println("Animal makes sounds.");
    }
}

class Dog extends Animal {
    @Override
    void makeSound() {
        System.out.println("Bow-wow!");
    }

    void wagTail() {
        System.out.println("Wagging the tail.");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal myAnimal = new Dog();  // 업캐스팅
        myAnimal.makeSound();  // 출력 : Bow-wow!, 오버라이딩된 메서드 호출

        if (myAnimal instanceof Dog) {  // instanceof로 변환 안전 확인
            Dog myDog = (Dog) myAnimal;  // 다운캐스팅 (명시적)
            myDog.wagTail();  // 출력 : Wagging the tail.
        }
    }
}

super, super()

  • super : 부모 클래스의 필드나 메서드를 호출할 때 사용
    • 부모의 메서드를 자식 클래스에서 오버라이딩 후 호출 가능 (예시 : super.메서드())
  • super() : 자식 클래스에서 부모의 생성자를 호출할 때 사용
    • 생성자는 기본적으로 상속되지 않으나, Sub Class의 생성자 안에 super(); 를 사용하여 가져올 수 있음
    • Sub Class에서는 반드시 super(); 를 이용한 생성자를 만들어야 하며, 생성하지 않으면 default 생성자가 생성됨
class Animal {
    String name;

    Animal(String name) {
        this.name = name;
    }

    void makeSound() {
        System.out.println(name + " makes sounds.");
    }
}

class Dog extends Animal {
    Dog(String name) {
        super(name);  // super()로 부모 클래스의 생성자 호출
    }

    @Override
    void makeSound() {
        super.makeSound();  // super로 부모 클래스의 메서드 호출
        System.out.println("Bow-wow!");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog myDog = new Dog("Poppi");
        myDog.makeSound();
    }
}

+ Recent posts