IT

객체지향 프로그래밍(OOP) 쉽게 이해하기: 상속, 다형성, 캡슐화, 추상화

0and24 2024. 11. 17. 18:30

안녕하세요! 오늘은 객체지향 프로그래밍(Object-Oriented Programming, OOP)의 기본 개념인 상속, 다형성, 캡슐화, 추상화에 대해 이야기해보겠습니다. 어려운 개념을 간단한 코드와 실생활 예시로 풀어볼게요!

OOP의 4 기둥들..

OOP란 무엇인가요?

객체지향 프로그래밍은 현실 세계를 프로그램으로 표현하기 위해 고안된 프로그래밍 방식입니다.

  • 현실의 사물(예: 자동차, 강아지)을 객체(Object)로 보고,
  • 이 객체들이 상호작용하며 프로그램이 동작하도록 설계합니다.

1. 상속(Inheritance)

상속은 부모 클래스의 속성과 메서드를 자식 클래스가 물려받는 것을 말합니다.

실생활 예시

"자동차(Car)"라는 부모 클래스가 있고, "스포츠카(SportsCar)"와 "트럭(Truck)"이라는 자식 클래스가 있다고 해볼게요.

  • 모든 자동차는 바퀴와 엔진이 있지만,
  • 스포츠카는 더 빠르고, 트럭은 더 많은 짐을 실을 수 있습니다.

코드 예시

// 부모 클래스
class Car {
    String brand = "Generic Car";
    void startEngine() {
        System.out.println("Engine started!");
    }
}

// 자식 클래스
class SportsCar extends Car {
    void turboBoost() {
        System.out.println("Turbo boost activated!");
    }
}

public class InheritanceExample {
    public static void main(String[] args) {
        SportsCar myCar = new SportsCar();
        myCar.startEngine(); // 부모 클래스 메서드 사용
        myCar.turboBoost();  // 자식 클래스 고유 메서드 사용
        System.out.println("Brand: " + myCar.brand);
    }
}

출력 결과

Engine started!
Turbo boost activated!
Brand: Generic Car

 

2. 다형성(Polymorphism)

다형성은 같은 메서드가 객체에 따라 다르게 동작하는 것을 의미합니다.

  • "다양한 형태를 가진다"는 뜻이에요.

실생활 예시

동물(Animal)이 울음소리(makeSound)를 낼 수 있는데,

  • 강아지(Dog)는 "멍멍!"
  • 고양이(Cat)는 "야옹!" 소리를 냅니다.

코드 예시

// 부모 클래스
class Animal {
    void makeSound() {
        System.out.println("Some generic animal sound...");
    }
}

// 자식 클래스
class Dog extends Animal {
    @Override
    void makeSound() {
        System.out.println("멍멍!");
    }
}

class Cat extends Animal {
    @Override
    void makeSound() {
        System.out.println("야옹!");
    }
}

public class PolymorphismExample {
    public static void main(String[] args) {
        Animal myAnimal = new Dog(); // 다형성 적용
        myAnimal.makeSound();        // 멍멍!
        
        myAnimal = new Cat();        // 다형성 적용
        myAnimal.makeSound();        // 야옹!
    }
}

출력 결과

멍멍!
야옹!

3. 캡슐화(Encapsulation)

캡슐화는 데이터를 숨기고, 필요한 경우에만 외부에서 접근을 허용하는 것입니다.

  • 객체 내부의 데이터를 보호하고, 잘못된 접근을 방지합니다.

실생활 예시

"은행 계좌(BankAccount)"를 생각해볼까요?

  • 외부에서는 직접 잔고(balance)를 수정할 수 없고,
  • 입금(deposit)이나 출금(withdraw)을 통해서만 조작이 가능합니다.

코드 예시

class BankAccount {
    private double balance; // 직접 접근 불가

    public BankAccount(double initialBalance) {
        this.balance = initialBalance;
    }

    // 입금 메서드
    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
            System.out.println(amount + "원이 입금되었습니다.");
        } else {
            System.out.println("올바른 금액을 입력하세요.");
        }
    }

    // 잔액 조회 메서드
    public double getBalance() {
        return balance;
    }
}

public class EncapsulationExample {
    public static void main(String[] args) {
        BankAccount myAccount = new BankAccount(1000);
        myAccount.deposit(500);
        System.out.println("현재 잔액: " + myAccount.getBalance() + "원");
    }
}

출력 결과

500원이 입금되었습니다.
현재 잔액: 1500원

4. 추상화(Abstraction)

추상화는 필요한 부분만 보여주고, 세부 사항은 감추는 것입니다.

  • 인터페이스나 추상 클래스를 통해 구현됩니다.

실생활 예시

리모컨(RemoteControl)을 생각해보세요.

  • 버튼을 눌러 TV를 켜고 끄는 방법은 알지만,
  • 내부의 전자 회로가 어떻게 작동하는지는 신경 쓰지 않습니다.

코드 예시

interface RemoteControl {
    void turnOn();
    void turnOff();
}

class TV implements RemoteControl {
    @Override
    public void turnOn() {
        System.out.println("TV를 켭니다.");
    }

    @Override
    public void turnOff() {
        System.out.println("TV를 끕니다.");
    }
}

public class AbstractionExample {
    public static void main(String[] args) {
        RemoteControl remote = new TV();
        remote.turnOn();
        remote.turnOff();
    }
}

출력 결과

TV를 켭니다.
TV를 끕니다.

마무리

객체지향 프로그래밍은 복잡한 코드를 더 현실적으로, 직관적으로 설계하도록 도와줍니다.

  • 상속으로 코드 재사용성을 높이고,
  • 다형성으로 유연한 동작을 만들며,
  • 캡슐화로 데이터를 보호하고,
  • 추상화로 중요한 것만 드러냅니다.