JAVA 기초

[JAVA 기초] JAVA의 정석 - Ch.07 객체지향 프로그래밍 II (정리)

beginner-in-coding 2025. 1. 15. 21:19

Ch.07 객체지향 프로그래밍 II


-      상속(inheritance)

  • 상속의 정의와 장점
    • 정의: 기존의 클래스를 재사용하여 새로운 클래스를 작성하는 것
      • 조상 클래스: 부모(parent) 클래스, 상위(super) 클래스, 기반(base) 클래스
      • 자손 클래스: 자식(child) 클래스, 하위(sub) 클래스, 파생된(derived) 클래스
    • 생성자와 초기화 블럭은 상속되지 않음
    • 자손 클래스의 멤버 개수 >= 부모 클래스의 멤버 개수
    • 자식클래스 extends 부모클래스 {  //자식 클래스의 내용  }  //t사용 방법
    • 장점
      • 코드의 재사용성, 중복을 줄임
      • 생산성과 유지보수에 용이
  • 클래스간의 관계 – 포함 관계
    • 포함(composite): 상속 이외의 클래스를 재사용하는 방법
    • 클래스의 멤버변수로 다른 클래스 타입의 참조변수를 선언하는 것
  • 클래스간의 관계 결정하기
    • 상속 관계: A는 B이다
    • 포함 관계: A는 B를 가지고 있다
  • 단일상속(single inheritance)
    • 하나의 클래스만을 상속받을 수 있다는 의미
    • 다중 상속의 단점인 상속받은 클래스들의 멤버간의 중복을 피하기 위해 단일 상속
  • Object 클래스 – 모든 클래스의 조상
    • 상속 계층도의 최상위 클래스
    • 컴파일러가 자동으로 Object 클래스의 상속을 추가
    • 모든 인스턴스가 가져야하는 기본적인 메서드 정의되어 있음

-      오버라이딩(overriding)

  • 오버라이딩이란
    • 조상 클래스로부터 상속받은 메서드를 자손 클래스에 맞게 변경(재정의)하는 것
    • @override 애너테이션
  • 오버라이딩의 조건
    • 성립 조건: 자손 클래스에서 오버라이딩하는 메서드는 조상 클래스의 메서드와
      1. 이름이 같아야함
      2. 매개변수가 같아야함
      3. 반환타입이 같아야함
    • 제약 조건: 조상 클래스의 메서드를 자손 클래스에서 오버라이딩할 때
      1. 접근제어자를 조상 클래스보다 좁게 설정할 수 없음
      2. 자손 클래스의 예외 개수 <= 조상 클래스의 예외 개수
      3. 인스턴스 메서드를 static 메서드나 그 반대로 행할 수 없음
  • 오버로딩 vs 오버라이딩
    • 오버로딩(overloading): 기존에 없던 새로운 메서드를 정의하는 것
    • 오버라이딩(overriding): 기존에 존재하던 상속받은 메서드를 재정의하는 것
  • super
    • 자손 클래스에서 사용하는 것
    • 조상 클래스로부터 상속받은 멤버를 참조하는데 사용
    • 자손 클래스와 조상 클래스의 멤버의 이름이 같을 경우 구분하기 위해 사용
  • super() – 조상 클래스의 생성자 호출
    • 자손 클래스에서 사용하는 것
    • 조상 클래스의 생성자를 호출할 때 사용
    • 생성자의 첫 줄에 호출해야함
      • 자손 클래스의 멤버가 조상 클래스의 멤버를 사용할 수 도 있기 때문에 먼저 초기화되어야함
    • this() 또는 super()를 선언하지 않으면 컴파일러가 자동 추가

-      Package 와 import

  • 패키지(package)
    • 의미: 클래스의 묶음, 물리적으로 하나의 디렉토리
    • 그룹단위로 묶음으로써 효율적으로 관리 가능
    • 하나의 소스파일에는 첫 번째 문장으로 단 하나의 패키지 선언만 허용
    • 모든 클래스는 하나의 패키지에 속해야함
    • 계층 구조: 점(.)으로 구별
  • 패키지의 선언
    • package 패키지명;  //패키지 선언 방법
    • 반드시 주석과 공백을 제외한 첫 째 줄에 위치
    • 클래스명과 구분하기 위해 소문자로 정의
    • 이름 없는 패키지(unnamed package)
      • 패키지를 선언하지 않으면 기본적으로 제공하는 패키지
  • Import
    • 다른 패키지의 클래스를 사용할 때 사용
    • 사용하고자하는 패키지 정보를 입력해줌
    • 컴파일러가 컴파일시에 import문을 통해 소스파일에 사용된 패키지를 알아내고 모든 클래스이름 앞에 패키지명을 붙여줌
  • import문의 선언
    • 소스파일의 구성
      1. package문
      2. import문
      3. 클래스 선언
    • import 패키지명.클래스명;  //다른 패키지에 있는 클래스 이용하기 위한 선언 방법
    • import 패키지명.*;  //다른 패키지 안에 있는 모든 클래스를 사용하겠다는 의미
    • 성능차이는 없음
  • static import
    • static 멤버를 호출할 때 클래스 이름을 생략할 수 있음
    • 자주 사용하는 클래스를 import해주면 코드가 간결해짐

-      제어자(modifier)

  • 제어자란?
    • 클래스, 변수, 메서드의 선언부 앞에 사용됨
    • 부가적인 정보를 나타냄
    • 종류
      1. 접근 제어자: public, protected, (default), private
      2. 그 외: static, final, abstract, synchronized, volatile, ...
  • Static – 클래스의공통적인
    • 의미: 클래스의, 공통적인
    • 하나의 변수를 method area에서 모든 인스턴스가 공유고 접근가능함
  • Final, 마지막의변경될 수 없는
    • 의미: 마지막의, 변경될 수 없는
    • 사용 가능 
      • 클래스: 변경될 수 없는 클래스, 확장될 수 없는 클래스가 됨, 다른 클래스의 조상이 될 수 없음
      • 메서드: 변경 될 수 없는 메서드, 오버라이딩을 통해 재정의 할 수 없음
      • 멤버변수, 지역변수: 값을 변경할 수 없는 상수가 됨
  • Abstract – 추상의미완성의
    • 사용 가능 
      • 클래스: 클래스 내에 추상 메서드가 선언되어 있음을 알림
      • 메서드: 선언부만 작성, 구현부는 작성하지 않음
  • 접근 제어자(access modifier)
    • 종류
      • private: 같은 클래스
      • default: 같은 패키지
      • protected: 같은 패키지 + 다른 패키지의 자손 클래스
      • public: 접근 제한 없음
    • 사용 이유
      • 외부로부터 데이터 보호
      • 외부에 불필요한 내부에서만 사용되는 부분을 감추기 위해서
  • 제어자의 조합
    • 주의 사항
      1. static과 abstract를 같이 사용할 수 없음
      2. abstract와 final을 같이 사용할 수 없음
      3. abstract의 접근제어자는 private일 수 없음
      4. 메서드에 final과 private을 같이 사용할 필요 없음

-      다형성(polymorphism)

  • 다형성이란
    • 객체지향의 개념에서의 의미: 여러 가지 형태를 가질 수 있는 능력
    • 조상 클래스 타입의 참조변수로 자손 클래스의 인스턴스를 참조할 수 있는 능력
      • 반대로 자손 클래스 타입의 참조변수로 조상 클래스의 인스턴스를 참조 할 수 없음
      • 조상 클래스에는 자손 클래스에서 추가적으로 정의한 멤버 변수를 가지고 있지 않기 때문
    • 참조변수의 타입에 따라 사용할 수 있는 멤버의 개수가 달라짐
  • 참조 변수의 형변환
    • 자손 타입 → 조상 타입 (Up-Casting): 형변환 생략 가능
    • 자손 타입 ← 조상 타입 (Down-Casting): 형변환 생략 불가
    • 상속 관계가 아닌 클래스끼리 형변환 불가능
  • instanceOf 연산자
    • 객체의 타입 변환 확인 할 때 사용
    • true값을 얻는다는 것은 참조변수가 검사한 타입으로 형변환이 가능하다는 의미
    • 형변환 전 타입 체크 instanceOf를 통한 검사가 필수적임
  • 참조변수와 인스턴스의 연결
    • 조상 클래스와 자손 클래스에 중복으로 정의된 멤버 변수를 사용할 경우
      • 부모 클래스의 인스턴스를 사용할 경우에는 부모의 멤버 변수를 사용
      • 자손 클래스의 인스턴스를 사용할 경우에는 자손의 멤버 변수를 사용
  • 매개변수의 다형성
    • 메서드의 매개변수
      • 부모 클래스를 타입으로 사용하면 그 부모 클래스를 상속받은 자손 클래스들도 매개값으로 전달 가능함
  • 여러 종류의 객체를 배열로 다루기
    • 조상 타입의 배열을 만들어서 조상 타입을 구현한 클래스들을 배열로 다룰 수 있음
    • 인덱스로 접근하여 조상 타입에 정의된 공통적인 멤버를 사용할 수 있음

-      추상 클래스(abstract class)

  • 추상 클래스란
    • 미완성 클래스
    • 미완성 메서드를 가지고 있다는 의미
    • 추상 메서드를 가지고 있지 않아도 abstract을 붙일 수 있음
    • abstract class 클래스이름 {  //클래스 내용  }  //사용 방법
  • 추상 메서드(abstract method)
    • abstract 리턴타입 메서드이름();
    • 선언부만 존재, 몸통{}을 제거
  • 추상클래스의 작성
    • 추상화: 클래스간의 공통점을 찾아서 뽑아내는 과정
    • 구체화: 추상화된 개념을 상속을 통해 클래스를 구현, 확장하는 작업

-      인터페이스(interface)

  • 인터페이스란
    • 일종의 추상클래스
    • 기본 설계도
    • 다른 클래스를 작성하는데 도움을 줌
  • 인터페이스의 작성
    • interface 인터페이스이름 {  //인터페이스 클래스 내용  }  //인터페이스 생성 방법
    • 제약 사항
      1. 모든 멤버변수는 public static final, 생략 가능
      2. 모든 메서드는 public abtract, 생략 가능
      3. static과 디폴트 메서드는 예외
  • 인터페이스의 상속
    • 다중 상속 가능
  • 인터페이스의 구현
    • class 클래스이름 implements 인터페이스1, 인터페이스2, ... {  //클래스 내용  }
    • 일부분만 구현한다면 abstract를 붙여서 추상클래스로 선언
  • 인터페이스를 이용한 다중 상속
    • 선언부만 선언되어 있으므로 다중 상속을 통해 중복이 일어나도 문제가 일어나지 않음
  • 인터페이스를 이용한 다형성
    • 입터페이스의 참조 변수로 이 인터페이스를 구현한 클래스의 인스턴스를 참조할 수 있음
    • 인터페이스 타입으로 형변환도 가능
    • 리턴 타입이 인터페이스: 인터페이스를 구현한 클래스를 반환하겠다는 의미
  • 인터페이스의 장점
    • 개발 시간을 단축시킬 수 있음
    • 표준화 가능
    • 서로 관계없는 클래스들에게 관계를 맺어줄 수 있음
    • 독립적인 프로그래밍이 가능
  • 인터페이스의 이해
    • User: 클래스를 사용하는 쪽
    • Provider: 클래스를 제공하는 쪽
    • 메서드를 사용하는(호출) 부분에서는 사용하려는 메서드 선언부만 알면 됨
    • 직접적인 관계에서 간접적인 관계로 바뀜 
  • 디폴트 메서드와 static 메서드
    • 인터페이스에 메서드를 추가한다는 것: 인터페이스를 구현한 모든 클래스에 추가해야한다는 것
    • 디폴트 메서드: 추상 메서드의 기본적인 구현을 제공하는 메서드
      • 추상 메서드가 아니므로 기존에 인터페이스를 구현한 클래스들에서의 변경은 없음
      • 접근 제어자: public, 생략 가능
    • 충돌 경우
      1. 여러 인터페이스간의 디폴트 메서드의 충돌: 인터페이스를 구현한 클래스에서 오버라이딩
      2. 디폴트 메서드와 조상 클래스간의 충돌: 조상 클래스의 메서드 사용

-      내부 클래스(inner class)

  • 내부 클래스란
    • 사용 용도: AWT, Swing과 같은 GUI
    • 클래스 내의 클래스가 선언되는 것을 의미
    • 사용 이유: 두 클래스의 관계가 깊기 때문
    • 장점
      • 내부 클래스에서 외부 클래스의 접근이 용이
      • 코드의 복잡성을 줄일 수 있음 (캡슐화)
  • 내부 클래스의 종류과 특징
    • 종류
      1. 인스턴스 클래스
        • 외부 클래스의 멤버 변수 선언부에 위치
        • 외부 클래스의 인스턴스 멤버처럼 사용
        • 외부 클래스의 인스턴스 멤버들과 관련된 작업에 사용될 목적
      2. static 클래스
        • 외부 클래스의 멤버 변수 선언부에 위치
        • 외부 클래스의 static 멤버처럼 사용
        • 외부 클래스의 static 맴버, static 메서드에서 사용될 목적
      3. 지역 클래스
        • 외부 클래스의 메서드나 초기화블럭 안에 선언
        • 선언된 영역 내부에서만 사용 가능
      4. 익명 클래스
        • 클래스의 선언과 동시에 객체의 생성을 동시에 하는 클래스 (일회용)
  • 내부 클래스의 선언
    • 내부클래스의 선언 위치에 따라 유효범위(scope)과 접근성(access)를 가짐
  • 내부 클래스의 제어자와 접근성
    • 내부 클래스가 외부 클래스의 멤버변수와 같은 성질을 가짐
    • 따라서 접근제어자(abstract, final, private, protected)가 가능
    • static 내부 클래스만 static 멤버를 가질 수 있음
      • final과 static이 붙은 상수는 모든 내부클래스에서 선언 가능
    • 외부 클래스의 외부에서 내부 클래스를 접근하는 방법
      • Outer.Inner 인스턴스이름 = new Outer().new Inner();  //내부 클래스가 인스턴스 클래스인 경우
      • Outer.Inner 인스턴스이름 = new Outer().Inner();  //내부 클래스가 static인 경우
  • 익명 클래스(anonymous class)
    • 이름이 없음
    • new 조상클래스이름() {  //멤버 선언  }
    • new 인터페이스이름() {  //멤버 선언  }
    • 생성자를 가질 수 없음
    • 하나의 클래스를 상속받거나 구현할 수 있음(다중상속 불가)