Java Study - 6일차

안정후·2024년 3월 18일
0

Java-Study

목록 보기
6/7

< 상속 >

  • 상속 : 기존 클래스의 속성을 물려 받아 새로운 클래스를 생성하는 것
  • 상속을 사용하려면 extends 키워드를 사용하면 된다. 이 때, extends 대상은 하나만 선택할 수 있다. ⇒ ‘단일상속’! 자바에서는 ‘다중상속’을 지원하지 않는다.
  • implements 키워드를 이용한 ‘다중구현’은 허용한다.

< 상속과 메모리 구조 >

new ElectricCar() 를 호출하면 ElectricCar 뿐만 아니라 상속 관계에 있는 Car 까지 함께 포함해서 인스턴스를 생성한다. 참조값은 x001 로 하나이지만 실제로 그 안에서는 Car , ElectricCar 라는 두가지 클래스 정보가 공존하는 것이다. 상속이라고 해서 단순하게 부모의 필드와 메서드만 물려 받는게 아니다. 상속 관계를 사용하면 부모 클래스도 함께 포함해서 생성된다. 외부에서 볼때는 하나의 인스턴스를 생성하는 것 같지만 내부에서는 부모와 자식이 모두 생성되고 공간도 구분된다.

electricCar.charge() 를 호출하면 참조값을 확인해서 x001.charge() 를 호출한다. 따라서 x001 을 찾아서 charge() 를 호출하면 되는 것이다. 그런데 상속 관계의 경우에는 내부에 부모와 자식이 모두 존재한다. 이때 부모인 Car 를 통해서 charge() 를 찾을지 아니면 ElectricCar 를 통해서 charge() 를 찾을지 선택해야 한다. 이때는 호출하는 변수의 타입(클래스)을 기준으로 선택한다. electricCar 변수의 타입이 ElectricCar 이므로 인스턴스 내부에 같은 타입인 ElectricCar 를 통해서 charge() 를 호출한다.

electricCar.move() 를 호출하면 먼저 x001 참조로 이동한다. 내부에는 Car , ElectricCar 두가지 타입이 있다. 이때 호출하는 변수인 electricCar 의 타입이 ElectricCar 이므로 이 타입을 선택한다. 그런데 ElectricCar 에는 move() 메서드가 없다. 상속 관계에서는 자식 타입에 해당 기능이 없으면 부모 타입으로 올라가서 찾는다. 이 경우 ElectricCar 의 부모인 Car 로 올라가서 move() 를 찾는다. 부모인 Carmove() 가 있으므로 부모에 있는 move() 메서드를 호출한다.

  • 상속과 메모리 구조 정리
    • 상속 관계의 객체를 생성하면 그 내부에는 부모와 자식이 모두 생성된다.
    • 상속 관계의 객체를 호출할 때, 대상 타입을 정해야 한다. 이때 호출자의 타입을 통해 대상 타입을 찾는다.
    • 현재 타입에서 기능을 찾지 못하면 상위 부모 타입으로 기능을 찾아서 실행한다. 기능을 찾지 못하면 더 상위 부모에서 필요한 기능을 찾아본다. 계속 찾아도 없으면 컴파일 오류가 발생한다.

< 메서드 오버라이딩과 메모리 구조 >

  1. electricCar.move() 를 호출한다.
  2. 호출한 electricCar 의 타입은 ElectricCar 이다. 따라서 인스턴스 내부의 ElectricCar 타입에서 시작
    한다.
  3. ElectricCar 타입에 move() 메서드가 있다. 해당 메서드를 실행한다. 이때 실행할 메서드를 이미 찾았으므로 부모 타입을 찾지 않는다.

- 오버라이딩 vs. 오버로딩

  • 메서드 오버라이딩(Overriding) : 부모에게서 상속 받은 기능을 자식이 재정의 하는 것
  • 메서드 오버로딩(Overloading) : 메서드 이름이 같고 매개변수(파라미터)가 다른 메서드를 여러개 정의하는 것

- 참고) 메서드 오버라이딩 조건

  • 메서드 이름: 메서드 이름이 같아야 한다.
  • 메서드 매개변수(파라미터): 매개변수(파라미터) 타입, 순서, 개수가 같아야 한다.
  • 반환 타입: 반환 타입이 같아야 한다. 단 반환 타입이 하위 클래스 타입일 수 있다.
  • 접근 제어자: 오버라이딩 메서드의 접근 제어자는 상위 클래스의 메서드보다 더 제한적이어서는 안된다. 예를 들어, 상위 클래스의 메서드가 protected 로 선언되어 있으면 하위 클래스에서 이를 public 또는
    protected 로 오버라이드할 수 있지만, private 또는 default 로 오버라이드 할 수 없다.
  • 예외: 오버라이딩 메서드는 상위 클래스의 메서드보다 더 많은 체크 예외를 throws 로 선언할 수 없다. 하지만 더 적거나 같은 수의 예외, 또는 하위 타입의 예외는 선언할 수 있다. 예외를 학습해야 이해할 수 있다. 예외는 뒤에서 다룬다.
  • static , final , private : 키워드가 붙은 메서드는 오버라이딩 될 수 없다.
  • static 은 클래스 레벨에서 작동하므로 인스턴스 레벨에서 사용하는 오버라이딩이 의미가 없다. 쉽게 이야기해서 그냥 클래스 이름을 통해 필요한 곳에 직접 접근하면 된다.
  • final 메서드는 재정의를 금지한다.
  • private 메서드는 해당 클래스에서만 접근 가능하기 때문에 하위 클래스에서 보이지 않는다. 따라서 오버라이딩 할 수 없다.
  • 생성자 오버라이딩: 생성자는 오버라이딩 할 수 없다
  • 접근 제한자 복습 [private -> default -> protected -> public]
    • private : 모든 외부 호출을 막는다.
    • default (package-private): 같은 패키지안에서 호출은 허용한다.
    • protected : 같은 패키지안에서 호출은 허용한다. 패키지가 달라도 상속 관계의 호출은 허용한다.
    • public : 모든 외부 호출을 허용한다.
profile
매일 한 단계 더 발전해나가는 개발자입니다.

0개의 댓글