객체지향 프로그래밍(OOP) 4대 원칙 정리

DevBison·2025년 11월 18일

OOP(Object Oriented Programming)는
“데이터와 기능을 객체로 묶어 현실을 코드로 표현하는 방식”이다.
핵심은 아래 4가지이다.


1. 캡슐화 (Encapsulation)


┌───────────────────────┐
│       Player          │
│ ┌───────────────────┐ │
│ │   private:        │ │   ← 내부 숨김
│ │   Health = 100    │ │
│ └───────────────────┘ │
│                       │
│  public:              │
│   GetHealth()         │ ← 외부 접근 함수
│   TakeDamage()        │
└───────────────────────┘

핵심: 중요한 데이터는 감추고, 함수로만 접근하게 한다.

개념

  • 데이터(변수)와 기능(함수)을 객체 내부에 묶는다.
  • 중요한 데이터는 숨기고, 함수로만 접근하도록 만든다.

이유

  • 데이터 보호
  • 내부 구조가 바뀌어도 외부 코드가 영향을 덜 받음

예시

class Player
{
private:
    int Health;

public:
    Player() : Health(100) {}

    int GetHealth() const
    {
        return Health;
    }

    void TakeDamage(int Amount)
    {
        if (Amount < 0) return;
        Health -= Amount;
        if (Health < 0) Health = 0;
    }
};

2. 상속 (Inheritance)

       Character
    ┌────────────────┐
    │ Move()         │
    │ Jump()         │
    └────────────────┘
             ▲
             │ (is-a)
             │
    ┌────────────────┐
    │     Player     │
    │ Attack()       │ ← 자식만의 기능
    └────────────────┘

핵심: **부모 기능 물려받고, 자식은 기능을 추가 확장한다.**

개념

  • 부모 클래스를 기반으로 새로운 자식 클래스를 만드는 것
  • “is-a 관계”일 때 사용
    예) Player is a Character

이유

  • 공통 기능 재사용
  • 중복 코드 감소

예시

class Character
{
public:
    void Move() {}
    void Jump() {}
};

class Player : public Character
{
public:
    void Attack() {}
};

사용:

Player P;
P.Move();
P.Attack();

3. 다형성 (Polymorphism)

    Character* Ptr
           │
           ▼
 ┌───────────────────┐
 │   Attack()        │ ← 하나의 인터페이스
 └───────────────────┘
     ▲          ▲
     │ override │ override
     │          │

┌────────────────┐ ┌────────────────┐
│ Player │ │ Enemy │
│ Attack() │ │ Attack() │
└────────────────┘ └────────────────┘


`Ptr->Attack()` 호출 시:

- Player 객체면 → Player::Attack()
- Enemy 객체면 → Enemy::Attack()

핵심: **같은 함수 이름이지만 객체 타입에 따라 동작이 다르다.**

개념

  • 같은 함수 이름이지만 실제 실행되는 동작은 타입마다 다름
  • virtual / override 로 구현

이유

  • 다양한 객체를 같은 인터페이스로 다룰 수 있음

예시

class Character
{
public:
    virtual void Attack()
    {
        // 기본 공격
    }
};

class Player : public Character
{
public:
    void Attack() override
    {
        // 플레이어 공격
    }
};

class Enemy : public Character
{
public:
    void Attack() override
    {
        // 적 공격
    }
};

사용:

void DoAttack(Character* C)
{
    C->Attack(); // 타입별로 다르게 실행됨
}

4. 추상화 (Abstraction)


┌───────────────────────────┐
│        IWeapon             │
│  Fire() = 0 (규칙만 정의) │ ← 인터페이스
└───────────────────────────┘
▲             ▲
│ implement   │ implement
│             │
┌─────────────────┐   ┌─────────────────┐
│       Gun        │   │       Bow        │
│  Fire(): 총 발사 │   │ Fire(): 활 발사 │
└─────────────────┘   └─────────────────┘

핵심:
사용자는 Fire()만 알면 되고, 내부 구현은 몰라도 된다.

개념

  • 복잡한 내부 구현은 숨기고
  • 꼭 필요한 기능만 외부에 제공하는 것

이유

  • 코드 단순화
  • 실제 구현이 바뀌어도 외부 코드는 유지됨

예시 (순수 가상 함수)

class IWeapon
{
public:
    virtual ~IWeapon() {}
    virtual void Fire() = 0; // 반드시 구현해야 한다
};

class Gun : public IWeapon
{
public:
    void Fire() override { /* 총 발사 */ }
};

class Bow : public IWeapon
{
public:
    void Fire() override { /* 활 발사 */ }
};

사용:

void Use(IWeapon* W)
{
    W->Fire();
}

정리

  • 캡슐화
    → 변수 숨기고 함수로만 접근하도록 보호

  • 상속
    → 부모 기능 재사용, 구조적 코드 구성 가능

  • 다형성
    → 같은 함수 이름, 타입마다 다른 동작

  • 추상화
    → 핵심 기능만 공개, 복잡한 구현은 숨김


┌─────────────────────────────────────────┐
│             OOP 4대 원칙               │
├─────────────────────────────────────────┤
│ 1. Encapsulation  →  데이터 보호/은닉  │
│ 2. Inheritance     →  부모 기능 재사용 │
│ 3. Polymorphism    →  타입별 다른 동작 │
│ 4. Abstraction     →  핵심 기능만 노출 │
└─────────────────────────────────────────┘

profile
응애 개발자

0개의 댓글