상속 관계
상속은 객체 지향 프로그래밍의 핵심 요소 중 하나로, 기존 클래스의 필드와 메서드를 새로운 클래스에서 재사용 할 수 있게 해준다. 하나의 대상만 extends 키워드로 상속받을 수 있다.
- 부모 클래스(슈퍼 클래스)
- 상속으로 자신의 필드와 메서드 코드를 제공하는 클래스
- 자식 클래스를 정보를 모르고, 접근이 불가능하다
- 자식 클래스(서브 클래스)
- 부모 클래스로부터 필드와 메서드를 상속받는 클래스
- 부모 클래스 정보를 알고 있고, 접근이 가능하다
다중 상속
다중 상속이란 하나의 자식 클래스가 두 개 이상의 부모 클래스를 가질 수 있는 것을 의미한다. 하지만 자바에서 다중 상속은 다이아몬드 문제과 클래스 계층 구조이 복잡화? 때문에 불가능하다.
다이아몬드 문제는 같은 메서드 명을 가진 부모메서드 명이 중복될 때 어떤 것을 사용해야 할지 모르는 문제를 의미한다. 위에서 AirplaneCar는 Airplane의 move()를 오버라이드 해야할지, Car의 move()를 오버라이드 해야할지 정할 수 없다. 따라서 자바에서 자식 클래스는 하나의 부모 클래스를 가질 수밖에 없다.
상속과 메모리 구조
Car 클래스를 상속받는 ElectricCar가 있는 상황에서 메모리 구조는 다음과 같다.
new ElectricCar()를 호출하면 ElectricCar 뿐만 아니라 상속 관계에 있는 Car까지 함께 포함해서 인스턴스를 생성한다. 참조값 x001에 Car, ElectricCar 두가지 클래스 정보가 공존하고 있다.
→ 상속 관계를 사용하면 하나의 참조값에 자식/부모 클래스가 함께 생성되고, 공간도 각각 구분된다.
electricCar.charge() 호출
electricCar.charge()를 호출하면 electricCar는 ElectricCar의 인스턴스이므로, ElectricCar의 charge()를 선택해 호출한다.
이때 메서드는 호출하는 변수의 타입(클래스)을 기준으로 선택하는 것을 알 수 있다.
electricCar.move() 호출
electricCar.move()를 호출시 move()를 찾는 과정은 다음과 같다.
x001로 이동 → 호출 타입인 ElectricCar에서 move() 찾음 (없음) → 부모 클래스인 Car에서 move() 찾음 (있음) → Car의 move() 호출
핵심
- 상속 관계의 객체를 생성하면 그 내부에는 부모와 자식 인스턴스가 모두 생성된다.
- 상속 관계의 객체를 호출할 때, 호출자의 타입(변수의 타입)으로 대상 타입을 찾는다.
- ex. ElectricCar electricCar = new ElectricCar(); 에서 변수 electricCar의 타입인 ElectricCar가 타겟된다
- 현재 타입에서 기능을 찾지 못하면 상위 부모 타입으로 기능을 찾아서 실행한다.
- 기능을 찾지 못하면 컴파일 오류가 발생한다.
상속과 메서드 오버라이딩
메서드 오버라이딩(Method Overriding)은 부모에게서 상속받은 기능을 자식이 재정의 하는 것을 의미한다.
- @Override
- 상위 클래스의 메서드를 오버라이드하는 것을 나타내는 애노테이션(프로그램이 읽을 수 있는 특별한 주석)이다
- 실수로 오버라이딩을 못하는 경우를 방지하고 코드의 명확성을 보장할 수 있다
- 오버라이딩 규칙(메서드명, 오버라이딩 여부)을 지키지 않으면 컴파일 에러가 발생한다
메서드 오버라이딩 조건
- 메서드 시그니처 : 메서드 시그니처가 동일해야 한다(이름, 매개변수 타입, 순서, 개수)
- 반환 타입 : 반환 타입이 같아야 한다. 반환 타입이 하위 타입일 수 있다.
- 접근 제어자 : 오버라이딩 메서드의 접근 제어자는 상위 클래스의 메서드보다 더 제한적이어서는 안된다
- 예외 : 오버라이딩 메서드는 상위 클래스의 메서드보다 더 많은 체크 예외를 throws로 선언할 수 없다.
- static, final, private : 키워드가 붙은 메서드는 오버라이딩 될 수 없다
- 생성자 오버라이딩 : 생성자는 오버라이딩 할 수 없다
→ @Override 붙이고, 컴파일 에러 발생하지 않게만 작성하자!
super
super - 부모클래스에 대한 참조
부모와 자식의 필드명이 같거나 메서드가 오버라이딩 되어있으면, 자식 클래스의 필드와 메서드가 사용되기 때문에 자식에서 부모의 필드나 메서드를 호출할 수 없다. 이때 super 키워드를 사용하면 부모를 참조할 수 있다. 즉, super를 사용하면 부모의 필드, 메서드에 접근 가능하다.
super - 생성자
상속 관계의 인스턴스를 생성하면 메모리 내부에는 자식과 부모 클래스가 각각 다 만들어진다. Child를 만들면 부모인 Parent까지 함께 만들어지는 것이다. 따라서 자식, 부모 각각의 생성자도 모두 호출되어야 한다.
규칙 : 상속 관계를 사용하면 자식 클래스의 생성자에서 부모 클래스의 생성자를 반드시 호출해야 한다
- 상속 관계의 생성자 호출은 결과적으로 부모 → 자식 순서로 실행된다. 부모 데이터를 먼저 초기화한 후 자식 데이터를 초기화한다.
- 상속 관계에서 부모의 생성자를 호출할 때는 super(…)를 사용하면 된다. 이때 super는 생성자 첫줄에 위치해야한다(안그럼 컴파일 에러 난다).
Reference
인프런 '김영한의 실전 자바 - 기본편'
'Dev Language > Java' 카테고리의 다른 글
[자바/기본] 11. 다형성2 (0) | 2024.01.17 |
---|---|
[자바/기본] 10. 다형성1 (0) | 2024.01.17 |
[자바/기본] 8. final (0) | 2024.01.16 |
[자바/기본] 7. 자바 메모리 구조와 final (0) | 2024.01.16 |
[자바/기본] 6. 접근 제어자 (0) | 2024.01.16 |