STUDY/Java

[Java] 상속 (Inheritance)

ofijwe 2024. 10. 20. 22:05
반응형

📒 상속

1️⃣ 상속 (Inheritance: OOP Is PIE)

  • 기존(상위) 클래스의 자산(멤버)을 자식(하위) 클래스에서 재사용하기 위한 것
    • 상위 클래스의 생성자와 초기화 블록은 상속 X
  • 상위 클래스의 멤버를 물려 받기 때문에 코드 절감
    • 상위 클래스 코드 변경 시 하위 클래스에도 적용 → 유지 보수성 향상
  • 상속은 extends 키워드를 사용해 적용

2️⃣ Object 클래스

  • 모든 클래스의 조상 클래스
  • 별도의 extends 선언이 없는 클래스는 extends Object 가 생략됨.
  • 모든 클래스에는 Object 클래스에 정의된 메서드 O

3️⃣ 단일 상속 (Single Inheritance)

  • Java는 단일 상속만 지원
    • interface와 포함 관계(has a)로 단점 극복
  • 다중 상속 → 여러 클래스 기능 물려받을 수 O / but, 관계 복잡

4️⃣ 포함 관계

  • 상속 이외에 클래스를 재활용 하는 방법
    • 2개 이상의 클래스에서 특성을 가져올 때 하나는 상속, 나머지는 멤버 변수로 처리
    • 포함 관계 UML 표현 → 실선 화살표
    • 유지 보수성 확보
  • 상속을 할 것인지 포함을 할 것인지 중요
  • 어떤 클래스를 상속 받고 어떤 클래스를 포함해야 하는지 중요 → 프로젝트 관점 문제
    • 상속: is a 관계가 성립하는지
    • 포함: has a 관계가 성립하는지

📒 메서드 재정의

1️⃣ 메서드 오버라이딩(overriding)

  • 조상 클래스에 정의된 메서드를 자식 클래스에서 적합하게 수정하는 것
  • 오버로딩 → 계속 적재하는 것 / 오버라이딩 → 계속 덮어쓰는 것
  • 조건 → 조상부와 동일
    • 메서드 이름 동일 (조상이 물려준 메서드와)
    • 매개 변수 개수, 타입, 순서 동일
    • 리턴 타입 동일
    • 접근 제한자는 부모 보다 범위가 넓거나 동일
    • 조상보다 더 큰 예외를 던질 수 X

2️⃣ super 키워드

  • 나의 조상
  • this로 멤버에 접근했듯이 super를 통해 조상 클래스 멤버 접근
    • super. 을 이용해 조상의 메서드 호출로 조상의 코드 재사용
  • 변수의 scope
    • 사용된 위치에서 점점 확장해가며 처음 만난 선언부에 연결됨
    • method 내부 → 해당 클래스 멤버 변수 → 조상 클래스 멤버 변수
  • super()는 조상 클래스의 생성자 호출
    • 조상 클래스에 선언된 멤버들은 조상 클래스의 생성자에서 초기화가 이뤄지므로 이를 재활용
    • 자식 클래스에 선언된 멤버들만 자식 클래스 생성자에서 초기화
  • super()는 자식 클래스 생성자의 맨 첫 줄에서만 호출 가능
    • 생성자의 첫 줄에만 this() 또는 super()가 올 수 있음.
  • 명시적으로 this() 또는 super()를 호출하지 않는 경우 컴파일러가 super() 삽입
    • 맨 상위 Object까지 객체가 다 만들어지는 구조
    • class Person { String name; Person(String name) { this.name = name; } }
  • 생성자 호출과 객체 생성의 단계
  • class Person { String name; Person(String name) { this.name = name; } } public class SpiderMan extends Person { Spider spider = new Spider(); boolean isSpider; SpiderMan(String name, Spider spider, boolean isSpider) { super(name); this.spider = spider; this.isSpider = isSpider; } SpiderMans(String name) { this(name, new Spider(), true); } public static void main(String[] args) { Spider sman = new SpiderMans("피터 파커"); } }

3️⃣ Annotation

  • 사전적 의미 → 주석 / 컴파일러, JVM, 프레임워크 등이 보는 주석
  • 소스코드에 메타 데이터를 삽입하는 형태
    • 소스 코드에 붙여 놓은 라벨
    • 코드에 대한 정보 추가 → 소스 코드의 구조 변경, 환경 설정 정보 추가 등의 작업 진행
  • 기본 Annotation
    • @Deprecated : 컴파일러에게 해당 메서드가 deprecated 되었다고 알려줌
    • @Override : 컴파일러에게 해당 메서드는 override한 메서드 임을 알려줌 (반드시 super class에 선언되어 있는 메서드여야 함)
    • @SuppressWarnings : 컴파일러에게 사소한 warning의 경우 신경 쓰지 말라고 알려줌

📒 Package & import

1️⃣ Package

  • PC의 많은 파일 관리 → 폴더 이용
    • 유사한 목적의 파일 기준
    • 의미있는 이름으로 계층적 접근
  • 프로그램의 많은 클래스 → 패키지 이용
    • 의미있는 이름으로 만들고, . 을 통해 계층적 접근
    • 물리적으로 패키지는 클래스 파일을 담고 있는 디렉터리
    • package name + class name으로 클래스 구분 → fully qualified name
  • package 선언
    • package package_name;
    • 첫 문장에 하나의 패키지만 선언
    • 모든 클래스는 반드시 하나의 패키지에 속함 → 생략 시 default package에 속함 / but, 가급적 사용 X
  • 일반적인 package naming 툴
    • 소속, 프로젝트, 용도

2️⃣ import

  • 다른 패키지에 선언된 클래스를 사용하기 위한 키워드
    • 패키지와 클래스 선언 사이에 위치
    • 패키지와 달리 여러 번 선언 가능
  • 선언 방법
    • import 패키지명.클래스명;
    • import 패키지명.*; → 하위 패키지까지 import 하지 X
  • import한 package의 클래스 이름이 동일하여 명확히 구분해야 할 때 → 클래스 이름 앞에 패키지 명 입력
  • default import package
    • java.lang.*;

3️⃣ static import

  • static member에 대한 import
  • 자주 사용되는 static member를 import 하여 static member 이름만으로 접근

📒 제한자

1️⃣ 제한자

  • 클래스, 변수, 메서드 선언부에 함께 사용되어 부가적인 의미 부여
  • 종류
    • 접근 제한자
      • public
      • protected
      • (default = package)
      • private
    • 그 외 제한자
      • static : 클래스 레벨 요소 설정
      • final : 요소를 더 이상 수정할 수 없게 함
      • abstract : 추상 메서드 및 추상 클래스 작성
      • synchoronized : 멀티스레드에서의 동기화 처리
  • 하나의 대상에 여러 제한자 조합 가능 / but, 접근 제한자는 하나만 사용 가능
  • 순서 무관 → but, 일반적으로 접근 제한자를 맨 앞에 둠

2️⃣ final

  • 마지막, 더 이상 바뀔 수 없음
  • final class
    • 더 이상 확장할 수 X
    • 상속 금지 → 오버라이드 방지
  • final method
    • 더 이상 재정의 할 수 X
    • overriding 금지
  • final variable
    • 더 이상 값 변경할 수 X
  • Blank final
    • 값이 할당되지 않은 멤버 변수
    • final 멤버 변수에 초기 값이 할당되어버리면 모든 객체는 같은 값을 사용해야 함.
    • 객체가 생성되면 갑을 변경할 기회 X → 반드시 생성자에서 1회 초기화 가능
    • 생성자에서 초기화를 가제하는 역할
  • static final
    • 단지 final만 있으면 객체마다 갖는 값으로 공용성이 없음
    • 진정한 상수는 객체와 무고나하게 모두가 공용하는 값

3️⃣ 접근 제한자(Access modifier)

  • 멤버 등에 사용되며 해당 요소를 외부에서 사용할 수 있는지 설정
  • method override 조건 확인
    • 부모의 제한자 범위와 같거나 넓은 범위로만 사용 가능
  • Private < Default < Protected < Public
  • 접근 제한자 종류 & 차이

4️⃣ Sealed class

  • 봉인된 클래스로 특정 클래스에게만 상속 가능
  • 상속 계층 내에서 엄격한 제어
    • 프로그램 구조 명확하게 유지, 의도치 않은 상속으로 인한 복잡성 및 혼란 방지
    • 명확한 역할과 직무 분류가 중요한 개념에 주로 사용
  • 작성법
    • 클래스에 sealed 키워드 사용 → 상속을 허락하는 클래스를 permits 뒤에 나열
      • sealed가 선언된 클래스는 permits 반드시 필요
    • 구현 클래스에 필요한 키워드
      • sealed : 봉인된 클래스, 추가적으로 permits로 하위 클래스 나열 필요
      • final : 더 이상 상속 받을 수 없는 클래스
      • non-sealed : 봉인이 해제된 클래스 → 자유롭게 상속 가능
반응형