안녕하세요! 오늘은 객체지향 프로그래밍(Object-Oriented Programming, OOP)의 기본 개념인 상속, 다형성, 캡슐화, 추상화에 대해 이야기해보겠습니다. 어려운 개념을 간단한 코드와 실생활 예시로 풀어볼게요!
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를 끕니다.
마무리
객체지향 프로그래밍은 복잡한 코드를 더 현실적으로, 직관적으로 설계하도록 도와줍니다.
- 상속으로 코드 재사용성을 높이고,
- 다형성으로 유연한 동작을 만들며,
- 캡슐화로 데이터를 보호하고,
- 추상화로 중요한 것만 드러냅니다.
'IT' 카테고리의 다른 글
자바에서의 Optional 사용법 및 NullPointerException 방지 (0) | 2024.11.19 |
---|---|
대칭키와 비대칭키란? (0) | 2024.11.18 |
마이그레이션이란? (0) | 2024.11.17 |
DTO와 Entity, VO의 차이점, 개념, 그리고 분리의 목적 (0) | 2024.11.16 |
Java 오버로딩(Overloading)과 오버라이딩(Overriding)??? (3) | 2024.11.15 |