카테고리 없음

6. Inheritance and Polymorphism

aerimi-code 2025. 5. 27. 15:32

자바에서는 상속관계가 중요하다



이 과정은 부모 클래스의 멤버를 자식 클래스가 물려받는것!

다중상속X: 자바에서는 클래스마다 파일 하나씩 사용하는 게 원칙이다..
여러 파일이어도 서로 클래스 간 접근이 가능하다. (접근이가능하다면)

 

상속받을때는 extends 를 이용한다



class Shape {

  // Shape class members

}

class Triangle extends Shape {

  // additional Triangle class members

}


이렇게하면 Trianlge 은 shpae을 상속한다. 

자식클래스는 부모클래스의 'is-a' 관계를 가진다. 



그럼 자식클래스와 부모클래스의 관계를 생성자 관계에서 살펴보자!



부모의 멤버는 상속되지만, 생성자는 상속되지 않는다.

대신 super() 를 사용하여 부모의 생성자를 호출할 수 있다. 


헉,, 그러면 서브클래스 마다 다 super() 를 해야하나요?? -> 아니요! 만약 안부르면 자동으로 기본 생성자 super()를 몰래 불러서 실행한다.

자바의 규칙: 자식클래스의 생성자가 실행되기 전에 부모 클래스의 생성자를 먼저 실행한다.

즉, 부모 생성자-> 자식 생성자 순서로 호출된다.

Triangle() {
    super();  // 자바가 자동으로 넣어줌! (보이지 않지만 무조건 실행됨!)
    this.numSides = 3;
}

그래서, 상속받은 클래스를 생성할 때 부모 클래스에서 상속받은 멤버중에 고정하고 싶은게 있다면 생성자를 사용하면 된다. 



주의할점!!
: 자바의 생성자에 대한 내용

클래스에서 생성자를 따로 만들지 않아도 자바가 자동으로 만들어주지만, 만약 내가 매개변수를 받는 생성자를 따로 만들고 기본 생성자(매개변수를 받지 않는 형태)를 명시하지 않았다면 이때는 자바가 자동으로 만들어주지 않는다.


따라서 이때 super() 를 하면 없는 생성자인 기본생성자 클래스이름() 형태를 부르기 때문에 오류가 나타나는 것이다. 









이런 부모와 자식클래스의 생성자 특징은 어디에 사용할 수 있을까요?? 




 

Parent Class Aspect Modifiers

 

자식 클래스가 부모의 private 멤버는 어떻게 될까???

 

우선 이걸 알아보려면 private의 특성에 대해 생각해보자
private는 해당 클래스 내부에서만 사용 가능하다는 특성이 있었다.

=> 따라서, 자식 클래스는 상속은 받되 접근이 불가하다.

class Shape {
    private double area;
}

class Triangle extends Shape {
    void printArea() {
        // System.out.println(area);  // ❌ 에러! 접근 불가!
    }
}



어 그럼,, 저 제 클래스에서도 이용하고 싶고 외부 패키지 접근은 막고싶은데 상속받은 자식클래스는 다 쓰게 해주면 좋겠어요!!

네! 그러면 protected 를 사용하세요! 

class Shape {
    protected double perimeter;
}

class Triangle extends Shape {
    void setPerimeter() {
        perimeter = 10.0;  // ✅ 가능!
    }
}

 

 

protected를 쓰면 자식 클래스에서 부모의 필드나 메서드에 접근할 수 있다!

 


final 키워드

어 근데 저는 자식 클래스에서 수정할 수 없게 하고싶어요..

그러면  final을 사용하세요!

class Shape {
    public final void draw() {
        System.out.println("Shape 그리기");
    }
}

class Triangle extends Shape {
    // public void draw() { ... }  // ❌ 컴파일 에러! final 메서드는 오버라이드 금지!
}

 

final 을 쓰면 아무리 자식이라도 절대 오버라이딩(수정)할 수 없다.

=> 부모클래스의 중요한 동작을 자식 클래스가 맘대로 바꾸는것을 막을 수 있다!! (실수나 버그 방지에 유용)  



접근제어자와 키워드의 순서

public final int width;


접근제어자,final,데이터타입,변수명으로 작성한다.

 


oop에서는 '다형성' 개념이 중요하다!

다형성: 많은 형태

  • 자바에서 다형성은 부모 클래스 타입의 변수에 자식 클래스 객체를 넣어서 사용할 수 있게 해주는 것
  • 즉, 부모 타입 = 자식 객체 가 가능하다는 뜻

만약 orange라고 생각하면 orange는 fruit의 자식이니까 fruit의 타입으로 객체를 생성할 수 있다. 

Fruit f = new Orange();


f는 Fruit타입으로 본 orange객체이다.


만약 부모 클래스의 메소드가 있다면 부모클래스를 상속받은 어떤 객체도 넣을 수 있다!

makeJuice(orange);  // Orange도 Fruit이니까 넣을 수 있음

 

makeJuice(Fruit fruit)라고 선언했더라도 orange는 fruit를 상속받았으니까 들어갈 수 있다!!!


fruit.squeeze()

하지만 이렇게 객체의 squeeze()를 호출한다면 orange클래스의 squeeze()가 호출된다. 

이해하기 어렵다면 
자바는 메서드를 실행할 때, 객체를 따라간다고 생각하면 된다! 실제로 생성된 객체를 orange이다. fruit가 아니라

fruit는 그냥 타입이다. 

 

이 개념이 바로 동적 바인딩이다! (실행될 때 따라가는 )

Q: 그러면 반대로 orange 타입으로 본 fruit도 가능하나요,,???
A. 아니요.. 

Fruit fruit = new Fruit();
Orange orange = fruit;  // ❌ 불가능


이유를 설명해보자면 Fruit는 일반적이라서 orange만의 메서드는 Fruit에 없기 때문이다 ! 

🌼 다형성의 장점

✅ 코드의 재사용성과 유연성 높아짐
✅ 메서드 매개변수를 부모 타입으로 만들어두면, 자식 객체 어떤 것이든 넣을 수 있음
✅ 복잡한 코드를 단순화할 수 있음



예시:

makeJuice(Fruit fruit) { ... }  // Fruit 타입 하나로 Apple, Orange, Banana 다 받을 수 있음!


오 이거 진짜 좋다..  잊고있었다... 


Method Overriding


Using a Child Class as its Parent Class