Dart에서 객체 간의 연관 관계와 Mixin, 그리고 추상 클래스에 대해 이야기해 보겠습니다.
1. 객체 간의 연관 관계
객체 간의 관계를 정의하는 객체지향 프로그래밍(OOP)에서는 연관 관계를 크게 두 가지로 나눌 수 있습니다:
컴포지션 관계와 집합 관계입니다.
컴포지션 관계
"강한 소유 관계"입니다.
- 전체(예: 자동차)가 사라지면, 부분(예: 엔진)도 함께 사라져야 합니다.
- 자동차와 엔진의 관계가 대표적인 예입니다.
class Engine {
final String type;
Engine(this.type);
void startEngine() {
print('${type} 엔진이 시동됩니다.');
}
}
class Car {
final Engine engine;
Car(String engineType) : engine = Engine(engineType) {
print('자동차 생성 완료.');
}
void startCar() {
engine.startEngine();
print("자동차가 출발합니다.");
}
}
void main() {
Car car = Car('V8');
car.startCar();
}
실행 결과
자동차 생성 완료.
V8 엔진이 시동됩니다.
자동차가 출발합니다.
집합 관계
"약한 소유 관계"입니다.
- 전체(예: 부서)가 없어져도 부분(예: 직원)은 독립적으로 존재할 수 있습니다.
- 부서와 직원의 관계가 대표적인 예입니다.
class Employee {
final String name;
Employee(this.name);
void displayEmployeeInfo() {
print('직원 이름: $name');
}
}
class Department {
final String deptName;
final List<Employee> employees;
Department(this.deptName) : employees = [] {
print('부서 생성 완료.');
}
void addEmployee(Employee emp) {
employees.add(emp);
}
void displayDepartmentInfo() {
print('부서 이름: $deptName');
for (var emp in employees) {
emp.displayEmployeeInfo();
}
}
}
void main() {
Department devDept = Department('개발부');
Employee emp1 = Employee('홍길동');
Employee emp2 = Employee('김철수');
devDept.addEmployee(emp1);
devDept.addEmployee(emp2);
devDept.displayDepartmentInfo();
}
실행 결과
부서 생성 완료.
부서 이름: 개발부
직원 이름: 홍길동
직원 이름: 김철수
2. Mixin (믹스인)
Mixin
Mixin은 코드를 재사용하기 위한 도구입니다.
- 여러 클래스에서 공통적으로 사용하는 기능을 쉽게 추가할 수 있습니다.
- 예를 들어, 자동차에 "엔진"과 "바퀴"라는 기능을 추가한다고 생각해 봅시다.
mixin Engine {
int power = 5000;
}
mixin Wheel {
String wheelName = '4륜 구동 바퀴';
}
class BMW with Engine, Wheel {}
void main() {
BMW bmw = BMW();
print('엔진 출력: ${bmw.power}');
print('바퀴 이름: ${bmw.wheelName}');
}
실행 결과
엔진 출력: 5000
바퀴 이름: 4륜 구동 바퀴
믹스인 클래스 인스턴스화하기
기본적으로 Mixin은 인스턴스화할 수 없지만, mixin class 키워드를 사용하면 가능해집니다.
mixin class Engine {
int power = 5000;
}
mixin class Wheel {
String wheelName = '4륜 구동 바퀴';
}
class BMW with Engine, Wheel {}
void main() {
BMW bmw = BMW();
Engine engine = Engine(); // 믹스인 클래스 인스턴스화
Wheel wheel = Wheel();
print('BMW 엔진 출력: ${bmw.power}');
}
3. 추상 클래스와 동적 바인딩
추상 클래스
추상 클래스는 설계도와 같아요.
- "이 클래스를 사용하는 모든 객체는 반드시 특정 동작을 가져야 한다."고 강제할 때 사용합니다.
abstract class Animal {
void performAction();
}
class Dog implements Animal {
@override
void performAction() {
print('멍멍 배고파!');
}
}
class Cat implements Animal {
@override
void performAction() {
print('야옹 배고파!');
}
}
동적 바인딩
- 동적 바인딩은 어떤 객체가 들어오더라도, 공통된 동작을 실행할 수 있는 방법입니다.
void start(Animal animal) {
animal.performAction();
}
void main() {
start(Dog());
start(Cat());
}
실행 결과
멍멍 배고파!
야옹 배고파!
정리
- 연관 관계
- 컴포지션 관계: 전체와 부분이 강하게 연결된 관계 (예: 자동차와 엔진).
- 집합 관계: 전체와 부분이 독립적으로 존재 가능한 관계 (예: 부서와 직원).
- Mixin (믹스인)
- 여러 클래스에서 공통된 기능을 쉽게 추가할 수 있음.
- with 키워드를 사용.
- mixin class를 사용하면 인스턴스화 가능.
- 추상 클래스와 동적 바인딩
- 추상 클래스는 공통 동작을 강제하는 설계도.
- 동적 바인딩을 통해 다양한 객체를 유연하게 처리 가능.