객체 지향 프로그래밍의 개념
1. 객체 지향 프로그래밍이란?
- Object-Oriented Programming, OOP
- 여러 독립적인 부품들의 조합, 즉 객체들의 유기적인 협력과 결합으로 파악하고자 하는 컴퓨터 프로그래밍의 패러다임
- 절차 지향 프로그래밍(순서대로 처리하여 결과를 도출)의 반대 개념
2. 객체란?
- 속성(attribute)과 행위(behavior)를 가진 모든 것
- 제임스 고슬링, "객체(object)란 클래스의 인스턴스나 배열을 말한다"
3. 클래스란?
- 어떤 문제를 해결하기 위한 데이터를 만들기 위해 추상화를 거쳐 집단에 속하는 속성(attribute)과 행위(behavior)를 변수와 메서드로 정의한 것
- 객체를 표현해주는 설계도
4. 인스턴스란?
- 클래스를 기반으로 한 변수를 실제 메모리에 할당된 것으로 실제 프로그램에서 사용되는 데이터
- 설계도를 바탕으로 구현된 구체적인 실체
객체 지향 프로그래밍의 장단점
1. 장점
- 프로그램을 보다 유연하고 변경이 용이하게 만들 수 있음
- 코드의 변경을 최소화하고 유지보수를 하는 데 유리
- 코드의 재사용을 통해 반복적인 코드를 최소화하고, 코드를 최대한 간결하게 표현 가능
- 인간 친화적이고 직관적인 코드
- 클래스 단위로 모듈화해서 개발 가능해서 대형 프로젝트에 적합
2. 단점
- 처리 속도가 상대적으로 느림
- 객체가 많으면 용량이 커질 수 있음
- 설계 단계에서 많은 시간과 노력이 필요
객체 지향 프로그래밍의 특징

1. 캡슐화 (Encapsulation)
- 서로 연관있는 속성과 기능들을 하나의 캡슐(capsule)로 만들어 데이터를 외부로부터 보호하는 것
a. 캡슐화의 목적
- 데이터 보호(data protection): 외부로부터 클래스에 정의된 속성과 기능들을 보호
- 데이터 은닉(data hiding): 내부의 동작을 감추고 외부에는 필요한 부분만 노출
- 외부로부터 클래스에 정의된 속성과 기능들을 보호 & 필요한부분만 외부로 노출
- class라는 캡슐로 객체 고유의 독립성과 책임 영역을 안전하게 지키고자 하는 목적
b. 접근제어자
- 클래스나 멤버들을 외부에서 접근하지 못하도록 접근을 제한하는 역할

2. 상속 (Inheritance)
- 기존의 클래스를 재활용하여 새로운 클래스를 작성하는 자바의 문법 요소
- 상위 클래스로부터 확장된 여러 개의 하위 클래스들이 모두 상위 클래스의 속성과 기능들을 간편하게 사용
- 반복적인 코드를 최소화하고 공유하는 속성과 기능에 간편하게 접근
class 부모{
}
class 자식 extends 부모{
}
3. 추상화 (Abstration)
- 객체의 공통적인 속성과 기능을 추출하여 정의하는 것
- 사물이나 표상을 어떤 성질, 공통성, 본질에 착안하여 그것을 추출하여 파악하는 것

a. 추상화 기법
- 분류 (Classification)
- 객체 -> 클래스
- 실재하는 객체들을 공통적인 속성을 공유하는 범부 또는 추상적인 개념으로 묶는 것
- 인스턴스화 (Instantiation)
- 클래스 -> 인스턴스
- 분류의 반대 개념. 범주나 개념으로부터 실재하는 객체를 만드는 과정
- 구체적으로 클래스 내의 객체에 대해 특정한 타입을 정의하고, 이름을 붙인 다음, 그것을 물리적인 어떤 장소에 위치시키는 등의 작업을 통해 인스턴스를 만드는 것을 말한다.
- ‘예시(Exemplification)’라고도 부른다.
b. 추상 클래스 (abstract class)
- 단일 상속만 가능
- 추상 메소드(자식클래스가 반드시 오버라이딩 해야됨)뿐만 아니라 일반클래스와 같이 일반적인 필드, 메서드, 생성자를 가질수 있음
- 추상화(추상 메서드)를 하면서 중복되는 클래스 멤버들을 통합 및 확장을 할 수 있다
- 추상클래스는 클래스간의 연관 관계를 구축하는 것이 초점
abstract class Exam {
int kor;
int eng;
int math;
abstract void total();
abstract void avg();
}
class NewlecExam extends Exam {
int com;
void total(){}
void avg(){}
}
class YBMExam extends Exam {
int toeic;
void total(){}
void avg(){}
}
c. 인터페이스 (interface)
- 클래스 다중 구현, 인터페이스끼리 다중 상속 가능
- 부모 자식 관계인 상속에 얽매이지 않고, 공통 기능이 필요할 때마다 추상 메서드를 정의해놓고 구현 (자유롭게 붙였다 뗐다 사용)
- 인터페이스는 클래스와 별도로 구현 객체가 같은 동작을 한다는 것을 보장하기 위해 사용하는 것에 초점
- 다중 구현이 된다는 점을 이용해, 내부 멤버가 없는 빈 껍데기 인터페이스를 선언하여 마커 인터페이스로서 이용 가능
interface Caculatable {
void total();
void avg();
}
interface Storable {
int getData();
}
class Exam implements Storable, Caculatable {
int kor;
int eng;
int math;
void total(){}
void avg(){}
int getData(){}
}
class File implements Storable {
String src;
boolean isFile(){}
void mkDir(){}
int getData(){}
}
4. 다형성 (Polymorphism)
- 객체 지향 프로그래밍의 꽃이라 불림
- 하나의 변수명, 함수명 등이 상황에 따라 다른 의미로 해석될 수 있는 것
- 어떤 객체의 속성이나 기능이 상황에 따라 여러 가지 형태를 가질 수 있는 성질
- 즉 오버라이딩(Overriding), 오버로딩(Overloading)이 가능
a. 메소드 오버로딩 & 오버라이딩
객체지향 프로그래밍의 설계 원칙 (SOLID)
1. SOLID란?
- 객체 지향 프로그래밍을 하면서 지켜야하는 5대 원칙
- 시간이 지나도 변경이 용이하고, 유지보수와 확장이 쉬워짐 (핵심은 추상화와 다형성)
- 5대 원칙: SRP(단일 책임 원칙), OCP(개방-폐쇄 원칙), LSP(리스코프 치환 원칙), ISP(인터페이스 분리 원칙), DIP(의존 역전 원칙)
2. SRP (단일 책임 원칙)
- 해당 모듈이 여러 대상 또는 행위들에 대해 책임을 가져서는 안되고, 오직 하나의 행위에 대해서만 책임을 져야 한다.
- 변경이 필요할 때 수정할 대상이 명확해짐
3. OCP (개방-폐쇄 원칙)
- 확장에 대해 열려있고 수정에 대해서는 닫혀있음
- 확장에 대해 열려 있다: 요구사항이 변경될 때 새로운 동작을 추가하여 애플리케이션의 기능을 확장
- 수정에 대해 닫혀 있다: 기존의 코드를 수정하지 않고 애플리케이션의 동작을 추가하거나 변경
- 개방 폐쇄 원칙을 지키기 위해서는 추상화에 의존 (변하는 것들은 숨기고 변하지 않는 것들에 의존)
4. LSP (리스코프 치환 원칙)
- 하위 타입은 상위 타입을 대체할 수 있어야 한다
- 해당 객체를 사용하는 클라이언트는 상위 타입이 하위 타입으로 변경되어도, 차이점을 인식하지 못한 채 상위 타입의 퍼블릭 인터페이스를 통해 서브 클래스를 사용할 수 있어야 한다는 것
- 대체 가능성을 결정해야 하는 것은 해당 객체를 이용하는 클라이언트
5. ISP (인터페이스 분리 원칙)
- 클라이언트의 목적과 용도에 적합한 인터페이스 만을 제공
- 목적과 관심이 각기 다른 클라이언트가 있다면 인터페이스를 통해 적절하게 분리
- 모든 클라이언트가 자신의 관심에 맞는 퍼블릭 인터페이스(외부에서 접근 가능한 메세지)만을 접근하여 불필요한 간섭을 최소화
6. DIP (의존 역전 원칙)
- 고수준 모듈은 저수준 모듈의 구현에 의존해서는 안 되며, 저수준 모듈이 고수준 모듈에 의존해야 한다는 것
- 비즈니스와 관련된 부분이 세부 사항에는 의존하지 않는 설계 원칙
- 고수준 모듈: 입력과 출력으로부터 먼(비즈니스와 관련된) 추상화된 모듈
- 저수준 모듈: 입력과 출력으로부터 가까운(HTTP, 데이터베이스, 캐시 등과 관련된) 구현 모듈
Getter & Setter
Getter,Setter를 사용하는 이유
- 메서드를 통해서 접근하기 때문에, 메서드 안에서 매개변수같이 어떤 올바르지 않은 입력에 대해 사전에 처리할 수 있게 제한하거나 조절할 수 있기 때문
참고자료