03. 객체지향 1/3
인프런의 부부 개발단 토토님의 즐거운 자바 강의를 정리한 내용
# 객체지향 프로그래밍
객체지향 프로그래밍 (Object-Oriented Programming, OOP)은 컴퓨터 프로그래밍의 패러다임 중 하나이다. 객체 지향 프로그래밍은 컴퓨터 프로그램을 명령어의 목록으로 보는 시각에서 벗어나 여러 개의 독립된 단위, 즉 “객체"들의 모임으로 파악하고자 하는 것이다. 각각의 객체는 메시지를 주고 받고 데이터를 처리할 수 있다.
예를 들어, 자동차를 가지고 싶다고 했을 때, 자동차 설계 도면을 가지고 싶다는 의미는 아니다. 설계 도면을 기반으로 만들어진 자동차를 가지고 싶다는 의미이다. 객체지향 프로그래밍이라는 뜻은 설계도를 통해 돌아가는 프로그래밍이 아니라 이 오브젝트, 인스턴스를 기반으로 돌아간다는 의미이다. 클래스만 가지고는 아무것도 못하고 클래스를 기반으로 인스턴스를 만들어야지만 사용할 수 있는 것이다.
클래스(Class) : 설계도
객체(Object) : 설계도를 기반으로 구현하고 싶은 대상
인스턴스(Instance) : 객체의 생성자를 통해 실체화 한 것
예시
- 컴퓨터(객체)를 만들어보자.
- 컴퓨터(객체)는 컴퓨터 설계도(클래스)를 이용해서 만들 것이다.
- 컴퓨터(객체)에는 CPU, RAM, 파워 등(필드)이 있음
- 컴퓨터(객체)에는 CPU 구동, RAM에 올리기 등(메서드)이 있음
- 컴퓨터(객체)를 만들면 설계도(클래스)대로 작동할 것이라고 기대함
- 컴퓨터(객체)를 공장(메모리)에서 만들면 실제 제품(인스턴스)이 생성됨
- 컴퓨터(객체)를 실제로 만들 때마다 시리얼 번호(메모리 상 주소)를 붙임
인스턴스는 우리가 사용하려면 특별한 이름으로 참조(reference)해야 한다.
- 참조형 변수(Reference Variable)를 선언
- 참조되지 않은 인스턴스는? 쓰레기(Garbage)
- new 클래스이름()이라는 것은 클래스 이름에 해당하는 인스턴스를 생성한다는 의미이다.
|
|
- 생성자로 인스턴스를 생성해야 책이 만들어지는 것
- 이 책을 참조하는 변수가
b
이다.Book
이라는 생성된 인스턴스를 참조한다. - 참조 변수
b
앞의 Book을 레퍼런스 타입이라고 한다.
- 만약에 참조하는 변수 없이
new Book();
만 한다면 Heap에 인스턴스는 생성된 상태이지만, 참조하는 녀석이 없다는 의미 - 참조하는 변수가 없을 경우 Heap 메모리에 생성된 인스턴스를 사용할 수 없다.
- 사용할 수 없는 인스턴스는 쓰레기(Garbage)이므로 GC 될 것
- 다시 말하지만, 참조형 타입은 값을 가지는 것이 아닌 객체를 참조하는 것
- 참조형 타입의 변수가 주소를 가지는 것처럼 설명하는 사람이나 책이 있는데, 자바는 어떤 주소에 어떤 값이 저장되는 지 알 수 있는 방법이 없다. 자바에는 그런 포인터 연산자가 없으므로 알 수 없다.
# 클래스
- 클래스는 필드(Field)와 메서드(Method)를 가진다.
- 필드는 클래스의 속성이라고 말할 수 있다.
- 메서드는 클래스의 기능, 행위라고 말할 수 있다.
# 클래스 선언 방법
클래스 앞에는 접근제한자(public, private, protected, default(없음))가 붙는다.
클래스 이름
- 첫 문자가 문자,
_
,$
의 특수문자로 시작되어야 하고 숫자로 시작할 수 없다. (참고로 한글도 가능하다) - 첫 문자가 아니라면 문자,
_
,$
, 숫자로 구성될 수 있다. JDK 8에서는_
한 글자로 이루어진 변수는 예약어로 정의되어 있기 때문에 사용할 수 없다. - 자바의 예약어는 식별자로 사용할 수 없다.
- 자바의 식별자는 대소문자를 구분한다.
- 식별자 길이는 제한이 없고 공백은 포함할 수 없다.
- 첫 문자가 문자,
클래스 이름 관례
- 클래스 명은 대문자로 시작
- 단어와 단어가 만날 경우 2번째 단어의 시작은 대문자로 시작
- HelloWorld 같이 적는 것, 이를 카멜 표기법이라고 함
|
|
# 클래스 다이어그램
static
이 붙은 메서드는 클래스 메서드- 클래스 메서드는 인스턴스를 생성하지 않아도 사용 가능
- 사용 가능하다는 것은 메모리에 올라가있다는 의미
VendingMachineMain은 VendingMachine에 의존한다.
- main 메서드가 동작하려면 VendingMachine 클래스 필요
- main 메서드가 쓰고 있으니까 필요한 것, 없으면 컴파일 에러
- 메서드 안에서 사용하는 것은 의존한다는 의미
- VendingMachineMain은
main(String[] args)
를 쓰니까 당연히 String 클래스에도 의존한다는 의미
- main 메서드가 동작하려면 VendingMachine 클래스 필요
# 클래스의 인스턴스 생성
인스턴스를 만드는 3가지 방법
- new 연산자와 생성자를 이용하여 인스턴스를 만드는 방법
- 클래스로더를 이용하는 방법
- 메모리에 있는 인스턴스를 복제(clone)하여 만드는 방법
2번 3번은 나중에 설명, 1번만 일단 이해하자
인스턴스를 만들 떄마다 메모리에 인스턴스가 생성되기에 필요한 개수만큼 잘 만드는 것은 매우 중요하다. 객체지향 프로그래밍에서 인스턴스 생성은 굉장히 중요하기 때문에 디자인 패턴에도 분류된다.
- 디자인 패턴 : 클래스를 작성하는 패턴
- 3가지 카테고리 중 인스턴스 생성 패턴이 있음. 그정도로 굉장히 중요!
# 메서드
# 메세지 교환
앨런 커티스 케이형이 말했다. 객체지향의 핵심은 “메시징"이다 !
- 훌륭하고 성장 가능한 시스템을 만들기 위한 핵심은 모듈 내부의 속성과 행동이 어떠한가보다 모듈이 어떻게 커뮤니케이션하는가에 달려있다.
- 객체지향 프로그래밍을 한다는 것은 메서드가 언제 호출되고, 어떻게 호출될까? 메서드의 이름은 어떻게 지어야 할까? 어떻게 호출해야 할까?를 고민해야 한다.
객체는 자율적인 책임을 가진다.
- 객체지향의 사실과 오해 책에 나오는 말
- 자율적인 객체란 스스로 정한 원칙에 따라 판단하고 스스로의 의지를 기반으로 행동하는 객체
- 객체가 어떤 행동을 하는 유일한 이유는 다른 객체로부터 요청을 수신했기 때문
- 요청을 처리하기 위해 객체가 수행하는 행동을 책임이라고 함
- 자율적인 책임의 특징은 객체가 어떻게 해야 하는가가 아니라 무엇을 해야하는가를 설명한다는 것이다.
메시징은 객체가 다른 객체의 메서드를 호출하는 것이라고 했고, 객체가 어떤 행동을 하는 유일한 이유는 이 객체의 메서드를 다른 객체가 호출했을 때이다. 즉, 핵심은 객체는 기능이 호출되었을 때 그에 맞는 기능을 하는 책임을 가지고 있다는 의미이다.
자판기의 동전 잔액을 보여주는 디스플레이 장치가 있다고 하면 어떤 책임이 있을까? 사용자가 넣은 동전의 정보를 정확히 표시해주는 책임이 있다. 상품 선택 버튼을 눌렀을때? 버튼은 잘 동작해야한다. 버튼에도 책임이 있다.
메서드 선언 방법
|
|
- 클래스 이름은 대문자로 시작하는 것이 관행
- 메서드 이름은 소문자로 시작하는 것이 관행
헷갈리지말자!!!
매개변수(parameter) : 메서드의 정의부분에 나열되어 있는 변수들을 의미
전달인자(argument) : 메서드를 호출할 때 전달되는 실제 값
# 메서드 선언방법
- 들어가는 것이 매개변수 나오는 것이 return
# static 메서드
static한 메서드는 인스턴스를 생성하지 않아도 호출할 수 있다.
- static 메서드는 인스턴스를 만들지 않아도 사용할 수 있다 !!!!!!!!
|
|
|
|
이렇게, 인스턴스를 생성하고 사용하는 것도 가능은 하다
- 하지만, 프로그래머끼리 관례상 static 메서드는
인스턴스.static메서드()
이렇게 쓰지말자 클래스.static메서드()
이렇게 쓰자
# 메서드 실행 시 발생하는 일
먼저, 자바 파일이 어떻게 실행되는지 알아보자. JVM은 어떤 경로에서 클래스 파일을 찾을까? 현재 폴더에 Hello.class 파일이 있다고 하더라도 현재 폴더에서 찾는다고 하면 틀렸다.
javac Hello.java
- 틀린 답 ) 현재 폴더에서 찾는다.
- 정답 ) JVM은 CLASSPATH 경로에서 클래스를 찾는다.
CLASSPATH=.
이라고 하면 CLASSPATH 경로가 현재 폴더(.
)으로 찎혀있다고 하면 현재 폴더에서 찾는 것이다.- 인텔리제이는 소스를 컴파일하고
out/production/프로젝트폴더
아래에 class 파일을 생성하기 때문에 해당 경로를 CLASSPATH로 인식하게 해준다.
java VendingMachineMain
- CLASSPATH에서 VendingMachineMain 클래스를 찾는다.
- JVM은 읽어들인 클래스 정보를 Metaspace라는 Native Memory 영역에 저장한다.
- 인스턴스가 아니라 클래스 자체에 대한 정보가 올라가는 것이다.
- JVM은 프로그램 시작점인 main 메서드를 metaspace에 저장된 VendingMachineMain에서 먼저 찾고 실행한다.
- JVM Stack이라고 불리는 메모리 영역에 실행된 메서드 정보를 올린다.
- 스택은 FILO (First In Last Out) 자료구조
- JVM Stack에 저장된 메서드 실행 정보 1개는 스택 프레임(Stack Frame)에 있다.
- main 메서드 안에 선언된 변수들은 스택 프레임에 저장되고 이러한 변수를 지역(local) 변수라고 한다.
- main에 있는
String[]
String 배열 인스턴스가 Heap 메모리에 생성된다.- 이 인스턴스를
args
변수가 참조한다. Stack Frame -> Heap
- 이 인스턴스를
- PC(Program Counter) Register를 통해 몇 번째 줄을 실행하고 있는지에 대한 정보도 기억하고 있다.
즉, 메서드가 실행될 때마다 JVM stack에 하나씩 올라가는 것이다.
- FILO 구조이니까 차곡차곡 쌓이는 것이다.
- 다쓰고 나면 빼서 제거하는 원리니까 당연히 main 메서드가 제일 아래에 위치
- 지역 변수는 메서드가 종료되면 사라진다. 스택에서 빠지니까. 즉, 메서드가 호출될 때 생성, 메서드가 종료될 때 지역변수 사라짐
- 만약, 같은 메서드를 동시에 10번 호출한다고 해도 그 메서드 안의 지역 변수는 각각 다른 영역에 저장되어 사용됨. 스레드마다 영역 다르니까.
- 즉, 동시에 메서드가 호출되어도 문제가 없다.
- 하지만, 메서드에서 클래스 안에 선언된 변수를 사용할 경우 문제가 발생할 수 있음
# Math Class
자바 API란 자바 개발자가 제공하는 명령어를 의미하고 API 문서란 이런 명령어들의 사용법과 규격을 제공하는 문서이다. Math Class를 Java Math API 문서에서 보도록 하자.
- Math Class가 가지고 있는 메서드는 모두 static한 메서드
- 이 말은 인스턴스를 만들 필요 없이 사용하다는 의미! 모든 필드와 메서드를!
|
|
# private
그런데, Math 클래스를 인스턴스 생성하여 사용하려고 하면 컴파일에러가 뜬다.
- 이 클래스를 만든 사람은 일부러 인스턴스 생성 안해도 사용할 수 있게 만든건데, 쓰는 사람이 인스턴스 생성해서 쓰면 메모리 낭비니까 강제로 막아뒀음
접근제한자를 public이 아닌 private으로 바꾸면, 해당 클래스 안에서만 접근 가능하다.
- 즉, 다른 클래스에서 인스턴스를 만들어서 사용할 수 없다.
- 인스턴스를 생성하지 못하면 인스턴스 메서드는 사용할 수 없고 static이 붙은 클래스 메서드만 사용할 수 있다.
- 여러 개 인스턴스를 생성하지 못하게 하고 강제로 static한 메서드만 사용하도록 하고싶으면 클래스 생성자의 접근제한자를 private으로 하면 됨