[Java] 객체지향개념 - 자바의 정석 기초편 7강 정리

이준영·2023년 10월 20일

Java

목록 보기
2/3
post-thumbnail

1. 상속(Inheritance)

  • 기존의 클래스로 새로운 클래스를 작성하는 것.(코드의 재사용)
  • 두 클래스를 부모와 자식으로 관계를 맺어주는 것.
  • 자손은 조상의 모든 멤버를 상속 받는다.(생성자, 초기화 블럭 제외)
  • 자손의 멤버 개수는 조상보다 적을 수 없다.(같거나 많다)
  • 자손의 변경은 조상에 영향을 끼치지 않는다.

클래스 간의 관계 결정

  • 상속관계 : '~은 ~이다.(is -a)'
  • 포함관계 : '~은 ~을 가지고 있다.(has -a)'
    • 클래스의 멤버로 참조변수를 선언하는 것
    • 작은 단위의 클래스를 만들고, 이들을 조합해서 클래스를 만든다.

단일 상속

  • Java는 단일상속만 허용한다.(C++은 다중상속 허용)
  • 비중이 높은 클래스 하나만 상속관계로, 나머지는 포함관계로 설정

Object 클래스

  • 모든 클래스의 조상
  • 부모가 없는 클래스는 자동적으로 Object클래스를 상속받게 된다.

오버라이딩(Overriding)

  • 상속 받은 조상의 메서드를 자신에 맞게 변경하는 것
  • 조건
    • 선언부가 조상 클래스의 메서드와 일치해야 한다.
    • 접근 제어자를 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없다.
    • 예외는 조상 클래스의 메서드보다 많이 선언할 수 없다.
  • 오버로딩 vs. 오버라이딩
    • 오버로딩 : 기존에 없는 새로운 메서드를 정의하는 것(new), 상속과는 관계 없음
    • 오버라이딩 : 상속 받은 메서드의 내용을 변경하는 것(change, modify)

생성자 super()

  • 조상의 생성자를 호출할 때 사용
  • 조상의 멤버는 조상의 생성자를 호출해서 초기화
  • 생성자의 첫 줄에 반드시 생성자를 호출해야 한다.
  • 그렇지 않으면 컴파일러가 생성자의 첫 줄에 super();를 삽입
  • 만약 super()에 대한 생성자가 부모 클래스에 없다면 에러 발생

참조변수 super

  • 객체 자신을 가리키는 참조변수. 인스턴스 메서드(생성자)내에만 존재
  • 조상의 멤버를 자신의 멤버와 구별할 때 사용

2. 패키지(Package)

  • 서로 관련된 클래스의 묶음
  • 클래스는 클래스 파일. 패키지는 폴더. 하위 패키지는 하위 폴더
  • 클래스의 실제 이름(full name)은 패키지를 포함

클래스 패스(classpath)

  • 클래스 파일의 위치를 알려주는 경로(path)
  • 환경변수 classpath로 관리하며, 경로간의 구분자는 ';'를 사용
  • classpath(환경변수)에 패키지의 루트를 등록해줘야 함

import문

  • 클래스를 사용할 때 패키지 이름을 생략할 수 있다.
  • 컴파일러에게 클래스가 속한 패키지를 알려준다.
  • java.lang 패키지의 클래스는 import 하지 않고도 사용할 수 있다.
  • import문의 선언
    • import 패키지명.클래스명;
    • import 패키지명.*;
  • 패키지문과 클래스 선언의 사이에 선언한다.
  • import문은 컴파일 시에 처리되므로 프로그램의 성능에 영향 없음.
  • 이름이 같은 클래스가 속한 두 패키지를 import할 때는 클래스 앞에 패키지명을 붙여줘야한다.
  • 다음의 두 코드는 서로 의미가 다르다.
import java.util.*;
import java.text.*;

import java.*; // java 패키지의 모든 클래스를 의미. 패키지는 포함 안됨

static import문

  • static 멤버를 사용할 때 클래스 이름을 생략할 수 있게 해준다.
  • 쓰는 이유 : 코드 가독성. 하지만 왠만하면 쓰지 않고 꼭 필요할 때만 사용

3. 제어자(Modifier)

  • 클래스와 클래스의 멤버(멤버 변수, 메서드)에 부가적인 의미 부여
  • 하나의 대상에 여러 제어자를 같이 사용가능(접근 제어자는 하나만)
  • 접근 제어자를 제일 왼쪽에 쓰는 것이 보편적
  • 접근 제어자 : public, protected, (default), private
  • 그 외 : static, final, abstract, native, transient, synchronized, volatile, strictfp
    • static : 클래스의, 공통적인
      • 멤버변수
        • 모든 인스턴스에 공통적으로 사용되는 클래스 변수가 된다.
        • 클래스 변수는 인스턴스를 생성하지 않고도 사용 가능하다.
        • 클래스가 메모리에 로드될 때 생성된다.
      • 메서드
        • 인스턴스를 생성하지 않고도 호출이 가능한 static 메서드가 된다.
        • static메서드 내에서는 인스턴스멤버들을 직접 사용할 수 없다.
    • final : 마지막의, 변경될 수 없는
      • 클래스
        • 변경될 수 없는 클래스, 확장될 수 없는 클래스가 된다.
        • final로 지정된 클래스는 다른 클래스의 조상이 될 수 없다.
      • 메서드
        • 변경될 수 없는 메서드
        • final로 지정된 메서드는 오버라이딩을 통해 재정의 될 수 없다.
      • 멤버변수, 지역변수
        • 변수 앞에 final이 붙으면, 값을 변경할 수 없는 상수가 된다.
    • abstract : 추상의, 미완성의
      • 클래스
        • 클래스 내에 추상 메서드가 선언되어 있음을 의미한다.
      • 메서드
        • 선언부만 작성하고 구현부는 작성하지 않은 추상 메서드임을 알린다.
      • 추상 클래스를 사용하려면 상속을 통해 클래스를 완성 시켜줘야 사용 가능(구상 클래스)

접근 제어자(access modifier)

  • private : 같은 클래스 내에서만 접근이 가능하다.
  • (default) : 같은 패키지 내에서만 접근이 가능하다.
  • protected : 같은 패키지 내에서 그리고 다른 패키지의 자손클래스에서 접근이 가능하다.
  • public : 접근 제한이 전혀 없다.
  • 클래스 : public, (default) 가능
  • 멤버 : public, (default), private, protected 모두 가능

캡슐화와 접근 제어자

  • 접근 제어자를 사용하는 이유
    • 외부로부터 데이터를 보호하기 위해서
    • 외부에는 불필요한, 내부적으로만 사용되는 부분을 감추기 위해서

3. 다형성(Polymorphism)

  • 여러 가지 형태를 가질 수 있는 능력
  • 조상 타입 참조 변수로 자손 타입 객체를 다루는 것
  • 객체와 참조변수의 타입이 일치할 때와 일치하지 않을 때의 차이
SmartTv s = new SmartTv(); // 모든 기능 사용 가능
Tv t = new SmartTv(); // 일부 기능 사용 불가능
  • 자손 타입의 참조변수로 조상 타입의 객체를 가리킬 수 없다.
Tv t = new SmartTv(); // 가능
SmartTv s = new Tv(); // 에러

참조변수의 형변환

  • 사용할 수 있는 멤버의 갯수를 조절하는 것
  • 조상 자송 관계의 참조변수는 서로 형변환 가능

instanceof 연산자

  • 참조변수의 형변환 가능여부 확인에 사용. 가능하면 true 반환
  • 형변환 전에 반드시 instanceof로 확인해야 함
  • 참조변수의 형변환은 왜 하나요?
    • 참조변수를 변경함으로써 사용할 수 있는 멤버의 갯수를 조절하기 위해서

매개변수의 다형성

  • 참조형 매개변수는 메서드 호출 시, 자신과 같은 타입 또는 자손타입의 인스턴스를 넘겨줄 수 있다.
class Product {}
class Tv extends Product {}
class Computer extends Product {}
class Audio extends Product {}

// 오버로딩 활용하여 작성
void buy(Tv t) {}
void buy(Computer c) {}
void buy(Audio a) {}

// 다형성 활용하여 작성 - 매개변수에 tv, computer, audio 다 들어올 수 있음
void buy(Product p) {} 

여러 종류의 객체를 배열로 다루기

  • 조상타입의 배열에 자손들의 객체를 담을 수 있다.
Product p[] = new Product[3];
p[0] = new Tv();
p[1] = new Computer();
p[2] = new Audio();

4. 추상 클래스(Abstract class)

추상 클래스

  • 미완성 설계도. 미완성 메서드를 갖고 있는 클래스
abstract class Player {
	abstract void play(int pos);
}
  • 다른 클래스 작성에 도움을 주기 위한 것. 인스턴스 생성 불가.
  • 상속을 통해 추상 메서드를 완성해야 인스턴스 생성 가능

추상 메서드

  • 미완성 메서드. 구현부(몸통)가 없는 메서드
  • 꼭 필요하지만 자손마다 다르게 구현될 것으로 예상되는 경우

추상 클래스의 작성

  • 여러 클래스에 공통적으로 사용될 수 있는 추상클래스를 바로 작성하거나 기존 클래스의 공통 부분을 뽑아서 추상 클래스를 만든다.
  • 추상화 ↔ 구체화
  • 추상화된 코드는 구체화된 코드보다 유연하다 = 변경에 유리

5. 인터페이스(Interface)

  • 추상 메서드의 집합
  • 구현된 것이 전혀 없는 설계도.(모든 멤버가 public)

인터페이스의 상속

  • 인터페이스의 조상은 인터페이스만 가능(Object가 최고 조상이 아님)
  • 다중 상속이 가능(추상 메서드는 충돌해도 문제 없음)

인터페이스의 구현

  • 인터페이스에 정의된 추상 메서드를 완성하는 것
    class 클래스이름 implements 인터페이스이름 { }
  • 일부만 구현하는 경우, 클래스 앞에 abstract를 붙여야 함
  • 추상 클래스와 차이점 : 인터페이스는 인스턴스 변수를 가질 수 없다.

인터페이스를 이용한 다형성

  • 인터페이스도 구현 클래스의 부모
  • 인터페이스 타입 매개변수는 인터페이스 구현한 클래스의 객체만 가능
    class Fighter extends Unit implements Fightable {
    	public void move(int x, int y) {}
    	public void attack(Fightable f) {} // Fightable 인터페이스를 구현한 클래스의 인스턴스만 가능하다는 뜻
    }
  • 인터페이스를 메서드의 리턴 타입으로 지정할 수 있다.

인터페이스의 장점

  • 두 대상(객체) 간의 연결, 대화, 소통을 돕는 중간 역할을 한다.
    • 구현체 변경에 유리
  • 선언(설계)와 구현을 분리시킬 수 있게 한다.
  • B가 변경되어도 A는 안바꿀 수 있게 된다.(느슨한 결합)
    • A → B 일때, B가 C로 바뀌면 A도 바꿔줘야 함.
    • A → I(인터페이스) → B 일때, B가 바껴도 A를 안 바꿔도 됨.
  • 직접적인 관계의 두 클래스(A-B)
  • 개발 시간을 단축할 수 있다.
  • 변경에 유리한 유연한 설계가 가능하다.
  • 표준화가 가능하다.
  • 서로 관계없는 클래스들을 관계를 맺어줄 수 있다.
    • marine, scv, tank → GroundUnit

디폴트 메서드와 static 메서드

  • 인터페이스에 디폴트 메서드, static 메서드 추가 가능(JDK 1.8 부터)
  • 인터페이스에 새로운 메서드(추상 메서드)를 추가하기 어려움(모든 구현체에 구현해줘야 하기 때문에
    • 해결책 = 디폴트 메서드
    • 디폴트 메서드는 인스턴스 메서드(기존의 인터페이스 원칙 위반이지만 예외적으로 허용)
      interface MyInterface {
      	default void method();
      }
    • 디폴트 메서드가 기존의 메서드와 충돌할 때의 해결책
      • 여러 인터페이스의 디폴트 메서드 간의 충돌 : 인터페이스를 구현한 클래스에서 디폴트 메서드를 오버라이딩해야 한다.
      • 디폴트 메서드와 조상 클래스의 메서드 간의 충돌 : 조상 클래스의 메서드가 상속되고, 디폴트 메서드는 무시된다.

6. 내부 클래스(Inner class)

  • 클래스 안의 클래스
    class A {
    	class B { }
    }

내부 클래스의 장점

  • 내부 클래스에서 외부 클래스의 멤버들을 쉽게 접근할 수 있다.
  • 코드의 복잡성을 줄일 수 있다.(캡슐화)

내부 클래스의 종류와 특징

  • 내부 클래스의 종류와 유효범위는 변수와 동일
    • 인스턴스 내부 클래스 : 외부 클래스의 멤버변수 선언위치에 선언하며, 외부 클래스의 인스턴스멤버처럼 다루어진다. 주로 외부 클래스의 인스턴스멤버들과 관련된 작업에 사용 될 목적으로 선언된다.
    • 스태틱 내부 클래스 : 외부 클래스의 멤버변수 선언위치에 선언하며, 외부 클래스의 static 멤버처럼 다루어진다. 주로 외부 클래스의 static멤버, 특히 static 메서드에서 사용 될 목적으로 선언된다.
    • 지역 내부 클래스 : 외부 클래스의 메서드나 초기화블럭 안에 선언하며, 선언된 영역 내부에서만 사용될 수 있다.
    • 익명 클래스(anonymous class) : 클래스의 선언과 객체의 생성을 동시에 하는 이름없는 클래스(일회용)
  • 내부 클래스의 제어자와 접근성
    • 내부 클래스의 제어자는 변수에 사용 가능한 제어자와 동일
    • 외부 클래스에선 (default), public만 가능하지만, 내부 클래스는 private, protected도 가능
profile
환영합니다!

0개의 댓글