티끌모아 태산

9. 상속 본문

백엔드/JAVA

9. 상속

goldpig 2024. 5. 30. 20:18
728x90

상속이란 기존 클래스를 재사용하여 새로운 클래스를 작성는 것이다. 상속은 코드의 재사용성을 높이고 코드의 중복을 제거하여 프로그램의 생산성과 유지보수에 크게 기여한다. 

  • 상속을 사용하려면 extends 키워드를 사용하고 extends 대상은 하나만 선택할 수 있다. 
  • 부모 클래스 (슈퍼 클래스): 상속을 통해 자신의 필드와 메서드를 자손 클래스에 제공하는 클래스.
  • 자손 클래스 (자식 클래스): 부모 클래스로부터 필드와 메서드를 상속받는 클래스

Car는 부모클래스이고 ElectricCar와 GasCar는 자손클래스이다.

상속은 부모의 기능을 자식이 물려받는 것이다. 따라서 자식은 부모의 기능을 물려 받아서 사용하고 있다. 하지만 부모 클래스는 자식 클래스에 접근할 수 없다

  • 자바는 다중 상속을 지원하지 않는다. 따라서 extends 대상은 하나만 선택할 수 있다. 즉, 부모는 여러개의 자식을 가질 수 있지만 자식은 하나의 부모만 선택할 수 있다. 
  • 생성자와 초기화 블럭은 상속되지 않는다. 오직 부모 클래스의 필드와 메서드만 상속된다.
  • 자손 클래스의 멤버 개수는 조상 클래스보다 항상 같거나 많다. 

⭐상속과 메모리 구조

ElectricCar electricCar = new ElectricCar();

new ElectricCar()를 호출하면 ElectricCar 뿐만 아니라 상속 관계에 있는 Car까지 포함해서 인스턴스가 생성된다. 참조값은 x001로 하나이지만 실제로 그 안에는 Car, ElectricCar 라는 두 가지 클래스 정보가 공존한다.  

  • 상속 관계의 객체를 생성하면 그 내부에는 부모와 자식이 모두 생성된다.
  • 상속 관계의 객체를 호출할 때, 호출자의 타입을 기준으로 대상 타입을 찾는다. 
  • 현재 타입에서 기능을 찾지 못했다면 상위 부모 타입으로 기능을 찾아서 호출한다. 최상위 클래스에서 기능을 찾지 못하면 컴파일 오류가 발생한다. 

상속과 메서드 오버라이딩

  • 오버라이딩: 부모 클래스로부터 물려받은 메서드의 내용(기능)을 자식 클래스에서 재정하는 것이다. 
  • 조건: 1. 메서드의 이름이 같아야 한다 2. 매개변수가 같아야 한다 3. 반환 타입이 같아야 한다. 
  • @Override 애노테이션 활용한다. 필수는 아니지만 코드의 명확성을 위해 붙여주는 것이 좋다. 

오버로딩메서드의 이름은 같지만 매개변수가 다른 메서드를 여러 개 정의하는 것이다. (기존에 없는 새로운 메서드를 정의하는 것이다.) 반면 오버라이딩은 상속받은 메서드의 내용을 변경하는 것이다. 

접근 제어자의 종류

  • private: 모든 외부 호출을 막는다.
  • default: 같은 패키지 안에서 호출을 허용한다.
  • protected: 같은 패키지 안에서 호출을 허용한다. 하지만 상속관계일 경우 패키지가 달라도 호출을 허용한다. 
  • public: 모든 외부 호출을 허용한다.

super - 부모 참조

super는 자손 클래스에서 부모 클래스의 멤버를 참조하는데 사용되는 참조 변수이다. 즉, super 키워드를 통해 부모를 참조할 수 있다. 

  • 조상 클래스의 멤버와 자손 클래스의 멤버가 중복 정의되어 서로 구별해야하는 경우에만 super를 사용하는 것이 좋다.

super() - 조상 클래스의 생성자

상속 관계의 인스턴스를 생성하면 결국 메모리 내부에는 자식과 부모 클래스가 모두 만들어진다. Child를 만들면 부모인 Parent까지 함께 만들어지는 것이다. 따라서 각각의 생성자도 모두 호출되어야 한다. 

  • 상속 관계를 사용하면 자식 클래스의 생성자에서 부모 클래스의 생성자를 반드시 호출해야한다. (규칙)
public class ClassB extends ClassA {
    public ClassB(int a){
        super(); // 부모 클래스의 기본 생성자 생략 가능
        System.out.println("ClassB 생성자 a=" + a);
    }
  • 부모 생성자를 호출할 때는 super()를 사용하면 된다.
  • this()는 같은 클래스의 다른 생성자를 호출할 때 사용하지만, super()는 조상 클래스의 생성자를 호출할 때 사용한다. 

Object클래스를 제외한 모든 클래스의 생성자 첫 줄에 생성자 this(), 또는 super()를 호출해야한다. 그렇지 않으면 컴파일러가 자동적으로 'super();'를 생성자의 첫 줄에 삽입한다. 하지만 만약 생성자가 정의되어 있으면, 기본생성자를 자동으로 생성해주지 않는다.

public class ClassC extends ClassB{
    public ClassC(){
        super(10,20); // 수퍼를 직접 정의해야한다.
        System.out.println("ClassC 생성자");
    }
}

클래스와 메서드에 사용되는 final

  • 클래스에 final: 상속 끝 즉, final로 선언된 클래스는 확장 될 수 없다. 따라서 다른 클래스가 final로 선언된 클래스를 상속받을 수 없다.
  • 메서드에 final: 오버라이딩 끝 즉, final로 선언된 메서드는 오버라이드 될 수 없다. 상속받은 서브 클래스에서 이 메서드를 변경할 수 없다.
728x90

'백엔드 > JAVA' 카테고리의 다른 글

10. 다형성(1)  (0) 2024.05.31
2. 기본형과 참조형  (0) 2024.03.04
1. 클래스와 데이터  (0) 2024.03.04