Java

상속

공부처음하는사람 2024. 6. 7. 02:59

 

상속 관계

상속은 기존 클래스의 필드와 메서드를 새로운 클래스에서 재사용하게 해준다.

상속을 사용하려면 extends 키워드를 사용한다. extends는 하나의 대상만 선택할 수 있다. (다중상속 불가능)

 

- 부모 클래스(슈퍼 클래스) : 상속을 통해 자신의 필드와 메서드를 다른 클래스에 제공하는 클래스

- 자식 클래스(서브 클래스) : 부모 클래스로부터 필드와 메서드를 상속받는 클래스

 

상속과 메모리 구조

Car 클래스를 상속받는 ElectricCar 자식 클래스가 있다고 가정해보자

new ElectricCar( )를 호출하면 ElectricCar뿐만 아니라 부모 클래스인 Car 클래스까지 함께 인스턴스 생성한다.

여기서 상속받는 메서드를 electricCar.method()를 호출하면, electricCar 클래스를 확인 후 Car 클래스로 올라가서 찾는다.

(그림은 method이지만 Car class에 move라는 메서드로 생각하자)

 

 

- 핵심내용 정리

1. 상속 관계의 객체를 생성하면 그 내부에는 부모와 자식이 모두 생성된다.

2. 상속 관계의 객체를 호출할 때, 대상 타입을 정해야 한다. (여기선 electricCar 변수의 타입이 EcectricCar이기에 먼저 호출한다.)

3. 현재 타입에서 메서드를 찾지 못했을 땐 상위 클래스로 올라가서 메서드를 찾아 실행한다. 못찾을 경우엔 컴파일 에러 발생

 

메서드 오버라이딩

부모 클래스의 메서드를 다르게 재정의 하고싶을 때 사용한다.

오버라이딩을 사용할 땐 @Override 어노테이션을 작성하자. 코드 실수를 막아줄 수 있다.

ctrl + O 단축키로 오버라이딩을 간편하게 작성할 수 있다.

 

오버라이딩의 작동 순서

- 위 핵심내용 2번처럼 대상타입이 정해져 있을 경우 대상 타입 먼저 메서드를 찾는다고 했다. 그 기능이 없을 때 상위 클래스로 올라간다.

하지만 그 기능(오버라이딩 된 메서드)가 있다면 대상 타입에서 바로 찾게 된다. 그러면 상위 클래스로 올라갈 필요가 없으므로 해당 메서드를 호출한다.

 

메서드 오버라이딩 조건

1. 메서드 이름이 같아야한다.

2. 파라미터 타입, 순서, 개수가 같아야한다.

3. 반환타입이 같아야 한다.

4. 접근 제어자는 상위 클래스의 메서드보다 더 제한적이지 않아야 한다.

(상위 클래스의 메서드가 protected일 때 public, protected는 가능, private, defualt는 불가능하다.)

5. 상위 클래스의 메서드보다 더 많은 체크 예외를 throw로 선언할 수 없다.

6. static, final, private 메서드는 오버라이딩 할 수 없다. (static은 클래스 레벨에서 작동하므로 오버라이딩의 의미가 없다)

7. 생성자는 오버라이딩 할 수 없다.

 

상속되는 메서드들은 접근 제어자의 영향을 받는다.

 

super - 부모 참조

부모와 자식의 필드명이 같거나 메서드가 오버라이딩 되어있으면 자식 클래스에선 부모 클래스의 필드나 메서드를 호출할 수 없다.

이럴 때 super 키워드를 사용해 부모 클래스를 참조할 수 있다.

 

super - 생성자

위에서 말했던 것 처럼 상속관계의 인스턴스를 생성하면 메모리 내에선 자식과 부모 클래스가 둘 다 만들어진다.

둘 다 만들어지면 당연히 생성자도 모두 호출이 되어야 한다.

 

생성자를 생성할 때, 기본 생성자는 생략된다. 따라서 super( ); 코드는 작성할 필요가 없다.

하지만 기본 생성자가 아닐 경우엔 super( ); 코드를 작성해 생성자를 호출해야 한다.

 

    public Movie(String name, int price, String director, String actor) {
        super(name, price);
        this.director = director;
        this.actor = actor;
    }

 

생성자는 하나만 호출할 수 있다. 두 개 이상의 생성자가 있을 때 하나를 선택하면 된다.

 

public class ClassB extends ClassA {

    public ClassB(int a) {
        super(); // 기본 생성자 생략 가능
        System.out.println("ClassB 생성자 a= " + a);
    }

    public ClassB(int a, int b) {
        super(); // 기본 생성자 생략 가능
        System.out.println("ClassB 생성자 a= " + a + " b = " + b);
    }
}

 

package extends1.super2;

public class ClassC extends ClassB {

    public ClassC() {
        super(10, 20);
        System.out.println("ClassC 생성자");
    }
}

(하나의 생성자를 선택)

 

상속 관계의 생성자 호출은 결과적으로 부모에서 자식 순서로 실행된다. super( );를 잘 보고 생각하자.

this를 사용하더라도 결국엔 super( )를 사용하게 된다.

 


 

오히려 기초 문법보다 객체지향 부분이 이해가 더 잘 된다. 이전에 그래도 조금 공부 했다고 이해가 더 쉽게 되는것 같다.

기초문법땐 그냥 그러려니 했지만 kotlin으로 인한 역체감이 슬슬 오는것 같다......

 

'Java' 카테고리의 다른 글

다형성 (2) - 추상클래스, 인터페이스  (0) 2024.06.12
다형성 (캐스팅, 메서드 오버라이딩)  (1) 2024.06.10
final  (0) 2024.06.06
접근 제어자  (0) 2024.05.28
생성자  (0) 2024.05.15