Java

[Java] 7. 상속

Empty_Bottle 2022. 6. 2. 15:18

제주도 도두동 무지개해안도로. 파도와 암석이 멋진 곳이었다.

7-1) 상속
- 이미 잘 개발된 클래스를 재사용해서 새로운 클래스를 만들기 때문에 중복되는 코드를 줄여준다.

- 부모 클래스의 수정으로 모든 자식 클래스들도 수정되는 효과를 통해 유지 보수 시간을 최소화할 수 있다.

  1. 클래스 상속
    • 자식 클래스를 선언할 때 어떤 부모 클래스를 상속받을 것인지를 결정하고, 선택된 부모 클래스는 extends 뒤에 쓴다.
      class 자식클래스 extends 부모클래스{
                     필드, 생성자, 메소드 등...
      }
    • 자바에서의 상속 특징
      ① 여러 개의 부모 클래스를 상속할 수 없다. (상속 받을 수 있는 대상이 여럿이 아닌 하나.)
      ② 부모 클래스에서 private 접근 제한을 갖는 필드와 메소드는 상속 대상에서 제외된다.
      ③ 부모 클래스와 자식 클래스가 다른 패키지에 존재한다면 default 접근 제한을 갖는 필드와 메소드도 상속 대상에서 제외된다.
  2. 부모 생성자 호출
    • 부모 생성자는 자식 생성자의 맨 첫 줄에서 호출된다.
    • super()은 부모의 기본 생성자를 호출. 
    • super(매개값, … )은 매개값의 타입과 일치하는 부모 생성자를 호출한다.
      - 매개값의 타입과 일치하는 부모 생성자가 없을 경우 컴파일러 에러가 발생한다.
    • super(매개값, … )이 생략된 경우 컴파일러에 의해 super()가 자동으로 추가되기 때문에 부모의 기본 생성자가 반드시 존재해야 한다.
  3. 메소드 재정의
    • 부모 클래스의 메소드 중 자식 클래스가 사용하기에 적합하지 않은 메소드의 경우 상속된 일부 메소드를 자식 클래스에서 다시 수정해서 사용하는 기능. (=Overriding)
    • 메소드 재정의 방법
      - 부모의 메소드와 동일한 시그너처(리턴 타입, 메소드 이름, 매개 변수 목록)를 가져야 한다.
      - 접근 제한을 더 강하게 재정의할 수 없다.
      - 새로운 예외(Exception)를 throws할 수 없다..
    • 부모 메소드 호출
      - 메소드가 재정의되었다면 부모 객체의 메소드는 숨겨지기 때문에 자식 객체에서 메소드를 호출하면 재정의된 자식 메소드가 호출된다.
      - 자식 클래스 내부에서 재정의된 부모 클래스의 메소드를 호출해야 하는 상황이 발생하면 명시적으로 super 키워드를 붙여서 부모 메소드를 호출할 수 있다. (    ≫ super.부모메소드();    )
  4. final 클래스와 final 메소드
    • final 키워드는 어떤 대상에 사용하느냐에 따라 해석이 조금씩 달라지지만 해당 선언이 최종 상태이고 결코 수정될 수 없음을 의미한다.
      - final 클래스: 해당 클래스는 최종적인 클래스이므로 상속할 수 없는 클래스.
      - final 메소드: 해당 메소드는 최종적인 메소드이므로 부모 클래스를 상속하여 자식 클래스를 선언할 때 자식클래스에서 해당 메소드를 재정의(Overriding)할 수 없음을 의미.

7-2) 타입 변환과 다형성

 - 다형성: 사용 방법은 동일하지만 다양한 객체를 이용하여 다양한 실행 결과가 나오도록 하는 성질.

  1. 자동 타입 변환
    • 타입을 다른 타입으로 변환하는 행위.
    • 클래스의 변환은 상속 관계에 있는 클래스 사이에서 발생. 
      - 자식은 부모 타입으로 자동 타입 변환이 가능.
    • 자동 타입 변환: 프로그램 실행 도중에 자동적으로 타입 변환이 일어나는 것
      ≫ 부모타입 변수 = 자식타입;
      - 자식은 부모의 특징과 기능을 상속받기 때문에 부모와 동일하게 취급될 수 있다.
      - 부모 타입으로 자동 타입 변환된 이후에는 부모 클래스에 선언된 필드와 메소드만 접근이 가능.
      - 변수는 자식 객체를 참조하지만 변수로 접근 가능한 멤버는 부모 클래스 멤버로만 한정된다.
         ⇒예외로 메소드가 자식 클래스에서 재정의되었다면 자식 클래스의 메소드가 대신 호출된다.
  2. 필드의 다형성
    • 필드의 타입을 부모 타입으로,,, P.337~350까지 1도 몰으갯읍니다 머,,, 어쩌갯읍니까 제가 멍청이지요,,,
  3. 매개 변수의 다형성
    • 메소드를 호출할 때에는 매개 변수의 타입과 동일한 매개값을 지정하는 것이 정석이지만 매개값을 다양화하기 위해 매개 변수에 자식 객체를 지정할 수도 있다.
    • 하핫 여기도 전혀 몰으갯는 걸~~~!~!~~!~!
    • 매개 변수의 타입이 클래스일 경우, 해당 클래스의 객체뿐만 아니라 자식 객체까지도 매개값으로 사용할 수 있다. (가 매우 중요한 것이라는데 무슨 말인지 이해가 되지 않는 나, 제법 멍청해요.)
  4. 강제 타입 변환
    • 부모 타입을 자식 타입으로 변환하는 것.
    • 자식 타입이 부모 타입으로 자동 변환한 후 다시 자식 타입으로 변환할 때 강제 타입 변환 사용 가능.
    • 자식 타입이 부모 타입으로 자동 타입 변환하면 부모에 선언된 필드와 메소드만 사용 가능한 제약 사항이 따름.
    • 자동 타입 변환된 상태에서 자식에 선언된 필드와 메소드를 꼭 사용해야 한다면 강제 타입 변환을 해서 다시 자식 타입으로 변환한 후 자식의 필드와 메소드를 사용한다.
  5. 객체 타입 확인
    • 부모 변수가 참조하는 객체가 부모 객체인지 자식 객체인지 확인하는 방법으로 instanceof 연산자를 사용한다.
      ≫   boolean result = 좌항(객체) instanceof 우항(타입)
      : 좌항이 우항의 타입으로 변환이 가능한지 확인하는 연산자로 가능하면 true를, 불가하면 false를 반환한다.(?)

7-3) 추상 클래스

 - 객체를 직접 생성할 수 있는 클래스를 실체 클래스라고 할 때 실체 클래스들의 공통적인 특성을 추출해서 선언한 클래스를 추상 클래스라고 한다. - 추상 클래스가 부모, 실체 클래스가 자식으로 구현되어 실체 클래스는 추상 클래스의 모든 특성을 물려받고, 추가적인 특성을 가질 수 있다.* 특성: 필드와 메소드

  1. 추상 클래스의 용도
    ① 공통된 필드와 메소드의 이름을 통일할 목적: 실체 클래스를 설계하는 사람이 여러 사람일 경우 데이터와 기능이 동일하지만 사람마다 각기 다른 이름으로 필드와 메소드를 설정하는 것을 방지할 수 있다. 
    ② 실체 클래스를 작성할 때 시간 절약:공통적인 필드와 메소드는 추상 클래스에 모두 선언해두고 다른 점만 실체 클래스에 선언하면 실체 클래스를 작성하는 데 시간을 절약할 수 있다. 
  2. 추상 클래스 선언
    • 클래스 선언에 abstract 키워드를 붙여 선언한다.
      ≫ public abstract class  클래스명{
               필드, 생성자, 메소드
           }
      - abstract를 붙이면 new 연산자를 사용하여 객체를 만들지 못하고 상속을 통해 자식 클래스만 만들 수 있다.
      - 일반 클래스와 마찬가지로 필드, 생성자, 메소드 선언을 할 수 있다.
      - new 연산자로 직접 생성자를 호출할 수는 없지만 자식 객체가 생성될 때 super(…)를 호출하여 추상 클래스 객체를 생성하므로 추상 클래스도 생성자가 반드시 있어야 한다.
    • 추상 클래스는 새로운 실체 클래스를 만들기 위해 부모 클래스로만 사용된다. 
  3. 추상 메소드와 재정의
    • 추상 클래스는 실체 클래스가 공통적으로 가져야 할 필드와 메소드들을 정의해놓은 추상적인 클래스로, 실체 클래스의 멤버(필드, 메소드)를 통일하는 데 목적이 있다.
    • 메소드의 선언만 통일하고 실행 내용은 실체 클래스마다 달라야 하는 경우에 추상 클래스는 추상 메소드를 선언할 수 있다. (아마도 동작(ex. 동물이 울다)은 같은데 내용(ex. 울음 소리)가 다른 케이스를 말하는 듯.)
      ≫[public | protected] abstract 리턴타입 메소드이름(매개변수, … );
    • 추상 클래스 설계 시 하위 클래스가 반드시 실행 내용을 채우도록 강제하고 싶은 메소드가 있을 경우 해당 메소드를 추상 메소드로 선언한다.
      => 자식 클래스는 반드시 추상 메소드를 재정의해서 실행 내용을 작성해야 하는데 그렇지 않으면 컴파일 에러 발생.