Java | 상속

Lumpen·2025년 4월 8일
0

Java

목록 보기
12/38

상속

상속은 객체 지향 프로그래밍의 핵심 요소 중 하나
기존 클래스의 필드와 메서드를 새로운 클래스에서 받아 재사용할 수 있다
extends 키워드로 사용 - 대상은 하나만 선택할 수 있다

상속 관계

  • 부모 클래스(수퍼 클래스): 상속을 통해 자신의 필드와 메서드를 다른 클래스에 제공하는 클래스
  • 자식 클래스(서브 클래스) 부모 클래스로부터 필드와 메서드를 상속받는 클래스

부모의 자원을 자식이 물려받기 때문에
자식은 부모 클래스에 접근 가능하지만
부모는 자식에게 접근할 수 없다

단일 상속

자바는 다중 상속을 지원하지 않는다
부모를 하나만 선택할 수 있다

다중 상속을 지원할 경우 다이아몬드 문제가 발생하게 된다
이는 여러 부모 중 어떤 자원을 받아서 사용할지 애매해지는 문제를 말한다
또한 클래수 계충 구조가 매우 복잡해질 수 있기 때문에 다중 상속ㅇㄹ 허용하지 않는다
대신 인터페이스 다중 구현을 허용한다

상속과 메모리 구조

자식의 인스턴스를 생성하면 상속 관계에 있는 부모까지 함께 포함하여
인스턴스가 생성된다
참조 값은 자식 인스턴스의 참조 값만 반환되지만 메모리에는 부모와 함께 생성되고 각각 메모리 공간도 구분되어 있다

상속 시 부모와 자식에 같은 메서드가 존재하게 되는데
이때는 호출하는 변수의 타입(클래스)을 기준으로 어떤 값 또는 메서드를 사용할지 결정한다
본인의 클래스에 호출하는 값이 없으면 부모 클래스에서 찾고
부모의 부모로 체이닝 되어 가장 상위의 부모에도 없으면 참조 에러가 발생한다

  • 상속 관계의 객체 생성 시 내부에는 부모와 자식 모두 생성된다
  • 상속 관계의 객체 호출 시 대상 타입을 정해야 한다 (호출자의 타입을 통해 대상 타입을 찾는다)
  • 현재 타입에서 기능을 찾지 못하면 부모 타입으로 체이닝 되어 찾아간다

상속과 기능 추가

상속 관계의 모든 클래스에 기능을 추가하려면
가장 상위 부모에 기능을 추가하면 모두 물려받게 된다

자식에게만 필요한 기능은 해당 클래스에 기능을 추가한다

메서드 오버라이딩

부모 타입의 기능을 자식에서는 다르게 재정의하여 사용할 수 있다
이를 오버라이딩이라고 한다
오버라이딩은 같은 이름으로 다른 기능의 메서드를 작성하는 것

public class ElectricCar extends Car {
	@Override
    public void move() {
    	System.out.println("전기차 move")
    }
}

@Override 어노테이션을 주어 오버라이드 하는 메서드임을 표시한다
이는 프로그램이 읽을 수 있는 특별한 주석에 해당한다
컴파일러는 이 어노테이션을 발견하면 메서드가 정확히 오버라이딩 되었는지 확인한다
그렇지 않을 경우 컴파일 에러

  • 상속 관계에서만 발생한다
  • 메서드 시그니처가 일치해야 한다 (이름, 매개변수, 반한타입이 같아야 한다)
  • 접근 제어자는 부모 클래스의 메서드 접근 제어자와 같거나 넓은 범위여야 한다
  • 부모 클래스의 메서드와 같거나 더 좁은 예외를 던질 수 있다
  • static, final, private 키워드를 사용한 메서드는 오버라이딩 될 수 없다
  • 생성자는 오버라이딩할 수 없다

static 의 경우 클래스 레벨에서 작동하기 떄문에 인스턴스 레벨에서의 오버라이딩은 의미가 없다
final 메서드는 재정의를 금지한다
private 메서드는 해당 클래스에서만 접근 가능하므로 하위 클래스에서 접근할 수 없다

오버라이딩 시 부모에만 있던 메서드가 자식 영역의 메모리에도 추가된다
오버라이딩은 재정의라고 한다

상속과 접근 제어

상속 관계에서 본인 타입에 없으면 부모 타입에서 기능을 찾는데
이 때 접근 제어자가 영향을 준다
메모리에서 자식과 부모가 구분되어 있기 때문이다
자식 타입에서 부모 타입의 기능을 호출 할 때 부모 입장에서는 외부에서 호출한 것과 같다

super

부모와 자식의 필드명이 같거나 메서드가 오버라이딩 되어 있으면
자식에서 부모 필드나 메서드를 호출할 수 없다
이 때 super 키워드를 사용하면 부모를 참조할 수 있다
이름 그대로 부모 클래스에 대한 참조를 나타낸다

생성자에서의 super

상속 관계의 인스턴스를 생성하면 메모리 내에 자식과 부모의 클래스가 모두 만들어진다
따라서 각각의 생성자도 모두 호출된다

상속 관계를 사용하면 자식 클래스의 생성자 첫 줄에서 부모 클래스의 생성자를 반드시 호출해야 한다
super(...) 형식으로 사용한다

생성자 첫줄에 this(...)를 사용할 수는 있지만 super(...)는 생성자 안에서 언젠가 반드시 호출해야 한다
부모 클래스의 생성자가 기본 생성자인 경우 super() 를 생략할 수 있다

부모의 생성자가 여러개인 경우 선택하여 생성할 수 있다

A <- B <- C 의 상속 관계 클래스가 있을 경우
C 의 인스턴스를 생성하더라도
A가 가장 먼저 생성되고, B, C 순서로 메모리에 올라간다
자식의 생성자에서 부모 클래스의 생성자인 super() 가 실행되기 때문

최상위 부모 A 에서 생성자 호출이 끝나면
B 생성자에게 그 다음 C 로 제어권이 이동한다

profile
떠돌이 생활을 하는. 실업자, 부랑 생활을 하는

0개의 댓글