객체지향프로그래밍의 3요소 5원칙 #1 - 3요소
개요
객체지향 프로그래밍(OOP)은 소프트웨어 개발에서 중요한 패러다임으로, 코드의 재사용성과 유지보수성을 높이는 데 큰 기여를 한다.
OOP는 객체 중심적인 사고를 하고 있으며 데이터를 추상화시켜 상태와 행위를 가진 객체를 만들고 객체 간의 유기적인 상호작용을 통해 로직을 구성하는 프로그래밍 방법이다.
이 글에서는 OOP의 핵심 캡슐화(Encapsulation), 상속(Inheritance), 다형성(Polymorphism)이라는 세 가지 요소를 간단한 예제와 함께 알아보자.
캡슐화(Encapsulation) = 정보은닉
데이터를 외부로부터 보호하고, 객체의 내부 구현을 숨기며, 외부에서는 공개된 인터페이스를 통해서만 객체와 상호작용하도록 하는 개념이다.
예제
balance
는 private
로 보호되고, 외부에서 deposit
과 withdraw
메서드로만 접근 가능하다.
#include <iostream>
using namespace std;
class BankAccount {
private:
double balance;
public:
BankAccount(double initialBalance) : balance(initialBalance) {}
void deposit(double amount) { balance += amount; }
void withdraw(double amount) { if (balance >= amount) balance -= amount; }
double getBalance() const { return balance; }
};
int main() {
BankAccount account(1000.0);
account.deposit(500.0);
account.withdraw(300.0);
cout << "Balance: " << account.getBalance() << endl;
return 0;
}
상속(Inheritance) = 재사용 + 확장
기존 클래스의 기능을 물려받아 새로운 클래스를 정의하는 방법이다. 이를 통해 코드 재사용성을 높이고 계층적 구조를 표현할 수 있다.
예제
Dog
클래스는 Animal
클래스의 기능을 물려받아 새로운 기능(bark()
)을 추가할 수 있다.
#include <iostream>
using namespace std;
class Animal {
public:
void eat() { cout << "This animal is eating." << endl; }
};
class Dog : public Animal {
public:
void bark() { cout << "Woof!" << endl; }
};
int main() {
Dog myDog;
myDog.eat(); // 부모 클래스 메서드 호출
myDog.bark(); // 자식 클래스 메서드 호출
return 0;
}
다형성(Polymorphism) = 사용편의
하나의 인터페이스로 다양한 객체를 처리할 수 있다. 특히, 가상 함수를 사용하여 런타임에 동적으로 동작을 결정한다.
- 오버라이딩(Overriding) : 부모 클래스에 정의되어 있는 메서드를 자식클래스에서 재정의하여 사용
- 오버로딩(Overloading) : 같은 이름을 가진 메서드를 인자값의 종류나 개수를 다르게 하여 다른 기능을 구현하도록 정의하여 사용.
예제
부모 클래스 포인터(Animal*
)를 통해 자식 클래스(Dog
, Cat
)의 메서드를 호출하며, 동적으로 동작합니다.
#include <iostream>
using namespace std;
class Animal {
public:
virtual void makeSound() { cout << "Some animal sound" << endl; }
};
class Dog : public Animal {
public:
void makeSound() override { cout << "Woof!" << endl; }
};
class Cat : public Animal {
public:
void makeSound() override { cout << "Meow!" << endl; }
};
int main() {
Animal* animal;
Dog dog;
Cat cat;
animal = &dog;
animal->makeSound(); // Dog의 makeSound() 호출
animal = &cat;
animal->makeSound(); // Cat의 makeSound() 호출
return 0;
}
결론
캡슐화, 상속, 다형성은 객체지향 프로그래밍의 핵심이며, 코드의 가독성과 재사용성을 크게 향상시킨다. 이 세 가지 요소를 잘 활용하면 더 견고하고 확장성 있는 소프트웨어를 설계할 수 있다.