
객체 지향 프로그래밍(Object-Oriented Programming, OOP)은 객체(Object) 를 중심으로 프로그램을 설계하고 개발하는 방식입니다.
자바(Java)는 대표적인 객체 지향 언어로, 현실 세계의 개념을 코드로 쉽게 표현할 수 있도록 설계되었습니다.
// 클래스 정의
public class Car {
private String brand;
private int speed;
public Car(String brand, int speed) {
this.brand = brand;
this.speed = speed;
}
public void accelerate() {
speed += 10;
System.out.println(brand + "가 가속하여 속도: " + speed);
}
}
// 객체 생성
public class Main {
public static void main(String[] args) {
Car myCar = new Car("Toyota", 0);
myCar.accelerate(); // Toyota가 가속하여 속도: 10
}
}
객체 지향 프로그래밍(OOP)은 다음 네 가지 핵심 개념을 기반으로 합니다.
| 특징 | 설명 |
|---|---|
| 캡슐화(Encapsulation) | 데이터 보호를 위해 필드를 숨기고, 접근을 제한 |
| 상속(Inheritance) | 기존 클래스를 재사용하여 새로운 클래스를 생성 |
| 다형성(Polymorphism) | 동일한 코드로 다양한 객체를 다룰 수 있도록 함 |
| 추상화(Abstraction) | 복잡한 내부 구현을 숨기고, 필요한 기능만 노출 |
public class Person {
private String name;
public String getName() { // Getter
return name;
}
public void setName(String name) { // Setter
this.name = name;
}
}
// 부모 클래스
public class Animal {
public void sound() {
System.out.println("동물이 소리를 냅니다.");
}
}
// 자식 클래스
public class Dog extends Animal {
@Override
public void sound() {
System.out.println("멍멍!");
}
}
// 실행 코드
public class Main {
public static void main(String[] args) {
Dog myDog = new Dog();
myDog.sound(); // 멍멍!
}
}
// 부모 클래스
public class Animal {
public void makeSound() {
System.out.println("동물이 소리를 냅니다.");
}
}
// 자식 클래스
public class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("야옹!");
}
}
// 실행 코드
public class Main {
public static void main(String[] args) {
Animal myAnimal = new Cat(); // 부모 타입으로 참조
myAnimal.makeSound(); // 야옹!
}
}
// 추상 클래스
abstract class Shape {
abstract void draw(); // 추상 메서드
}
// 구체 클래스
class Circle extends Shape {
@Override
void draw() {
System.out.println("원을 그립니다.");
}
}
SOLID 원칙은 객체 지향 프로그래밍에서 유지보수성과 확장성을 높이기 위해 따라야 하는 5가지 중요한 설계 원칙입니다.
| 원칙 | 설명 |
|---|---|
| S | 단일 책임 원칙(Single Responsibility Principle, SRP) |
| O | 개방-폐쇄 원칙(Open-Closed Principle, OCP) |
| L | 리스코프 치환 원칙(Liskov Substitution Principle, LSP) |
| I | 인터페이스 분리 원칙(Interface Segregation Principle, ISP) |
| D | 의존 역전 원칙(Dependency Inversion Principle, DIP) |
// 잘못된 설계: User 클래스가 데이터 처리까지 담당
public class User {
public void saveToDatabase() {
System.out.println("DB에 저장");
}
}
// 개선된 설계: User 클래스와 UserRepository 분리
public class User {
private String name;
}
public class UserRepository {
public void save(User user) {
System.out.println("DB에 저장");
}
}
// 확장 가능하도록 인터페이스 활용
interface Payment {
void pay();
}
class CreditCardPayment implements Payment {
public void pay() {
System.out.println("신용카드 결제");
}
}
class PayPalPayment implements Payment {
public void pay() {
System.out.println("PayPal 결제");
}
}
class Rectangle {
int width, height;
void setWidth(int width) { this.width = width; }
void setHeight(int height) { this.height = height; }
}
class Square extends Rectangle {
void setWidth(int width) {
super.setWidth(width);
super.setHeight(width);
}
}
위반 사례: 정사각형(Square)은 가로와 세로가 항상 같아야 하지만, Rectangle의 setWidth()와 setHeight()를 따르지 않아 LSP를 위반함.
interface Animal {
void eat();
void fly();
}
class Dog implements Animal { // 불필요한 fly() 메서드 강제됨
public void eat() {}
public void fly() {} // 개는 날지 못하지만 구현해야 함
}
잘못된 설계 → 동물마다 필요한 기능을 분리해야 함
interface Eatable { void eat(); }
interface Flyable { void fly(); }
class Bird implements Eatable, Flyable { public void eat() {} public void fly() {} }
class Dog implements Eatable { public void eat() {} }
class PaymentService {
private Payment payment; // 인터페이스를 의존
public PaymentService(Payment payment) {
this.payment = payment;
}
public void processPayment() {
payment.pay();
}
}