오늘의 질문
객체 지향 프로그래밍 (OOP, Object-Oriented Programming)
상태(필드)와 행위(메서드)를 가진 객체를 중심으로 프로그램을 설계하는 프로그래밍 패러다임이다. 객체에 역할과 책임을 부여하고, 이 객체들이 서로 협력하는 방식으로 프로그램을 구성한다.
객체 지향 프로그램의 특징
캡슐화 (Encapsulation)
객체의 상태와 행위를 하나의 단위로 묶는다. 내부 구현은 숨기고 외부에서 접근할 수 있는 인터페이스만 제공함으로써 객체의 무결성을 보호하고 코드의 유지보수성을 높일 수 있다.
추상화 (Abstraction)
불필요한 세부 사항을 감추고 핵심적인 기능만 간추리는 것을 말한다. 객체의 공통적인 특징은 추출하여 인터페이스 또는 추상 클래스로 정의하고 구체적인 세부 사항은 구현체에게 위임함으로써 객체의 핵심 기능에만 집중할 수 있다.
다형성 (Polymorphism)
하나의 인터페이스가 여러 형태르 동작할 수 있는 것을 말한다. 오버로딩과 오버라이딩을 사용하여 같은 메서드 명이더라도 객체에 따라 다른 방식으로 동작하도록 할 수 있다.
상속 (Inheritance)
상위 클래스의 특징을 하위 클래스가 물려받아 확장하는 것을 말한다. 기존 기능을 수정하지 않고 새로운 기능을 추가할 수 있어 확장성이 뛰어나고, 중복을 제거하여 코드의 재사용성을 높일 수 있다.
TDA 원칙
TDA(Tell Don’t Ask) 원칙은 객체의 데이터를 직접 요청하지 말고 객체에게 필요한 동작을 수행하도록 메시지를 보내라는 원칙이다. TDA 원칙에 따르면 캡슐화를 지킬 수 있고, 객체 스스로 데이터를 다루기 때문에 객체의 응집도를 높이고 객체 간 결합도를 낮출 수 있다.
// 준수 예시 (Good)
public class Account {
private BigDecimal balance;
public Account(BigDecimal balance) {
this.balance = balance;
}
public void withdraw(BigDecimal withdrawalAmount) {
if (balance.compareTo(withdrawalAmount) < 0) {
throw new IllegalStateException("잔액이 부족합니다.");
}
this.balance = balance.subtract(withdrawalAmount);
}
}
Account account = new Account(BigDecimal.TEN);
BigDecimal withdrawalAmount = BigDecimal.ONE;
account.withdraw(withdrawalAmount); // 객체에 메시지 전달
// 위반 예시 (Bad)
public class Account {
private BigDecimal balance;
public Account(BigDecimal balance) {
this.balance = balance;
}
public BigDecimal getBalance() {
return this.balance;
}
public void setBalance(BigDecimal balance) {
this.balance = balance;
}
}
Account account = new Account(BigDecimal.TEN);
BigDecimal withdrawalAmount = BigDecimal.ONE;
BigDecimal balance = account.getBalance(); // 객체의 데이터를 직접 가져와서 사용
if (balance.compareTo(withdrawalAmount) < 0) {
throw new IllegalStateException("잔액이 부족합니다.");
}
balance = balance.subtract(withdrawalAmount);
account.setBalance(balance);
추상 클래스와 인터페이스의 차이
추상 클래스는 공통된 기능을 재사용하려는 목적으로 사용된다. 일반 메서드와 추상 메서드를 포함할 수 있고, 인스턴스 변수를 가질 수 있다. 인터페이스는 구현을 강제하려는 목적으로 사용된다. 추상 메서드와 상수만 가질 수 있다. 코드의 재사용이 중요한 경우 추상 클래스를 사용하고, 다중 상속이 필요한 경우 인터페이스를 사용한다.
🔖 참고자료