#06 Dart 언어 기본 문법 - Mixin & 추상 클래스
목차
Ⅰ OOP 객체 관계
01. OOP 객체 관계란?
객체 관계
- 객체 지향 프로그래밍에서 객체 관계란 프로그램을 구성하는 여러 객체들이 서로 상호작용하고 연결되는 방식을 의미
- 객체들이 서로 독립적으로 존재하는 것이 아니라, 다른 객체와 관계를 맺고 협력하여 기능을 수행 함
- 객체 간의 관계를 잘 설계하면 코드의 재사용성, 유지 보수성, 확장성을 높일 수 있음
- 객체의 관계는 [연관 관계, 상속 관계, 의존 관계]로 분류
02. 연관 관계 (Association)
연관 관계
- 연관 관계란 객체들이 서로 연결되어 있는 관계
- 컴포지션 관계와 집합 관계로 분류
컴포지션 관계 (Composition)
- [부분-전체] 관계 중에서 생명 주기가 밀접하게 연관된 강한 소유 관계를 의미
- 전체 객체가 소멸될 때 부분 객체도 함께 소멸, 부분 객체는 전체 객체에 종속
// 부분 객체
class Engine {
final String type;
Engine(this.type);
void startEngine() {
print('${type} 엔진이 시동됩니다.');
}
}
// 전체 객체
class Car {
final Engine engine;
Car(String engineType) : engine = Engine(engineType);
void startCart() {
engine.startEngine();
print('차가 출발합니다.');
}
}
void main() {
// 부분 객체의 생명주기를 전체 객체에서 관리
Car car = Car('v8');
}
집합 관계 (Aggregation)
- [부분-전체] 관계 중에서 전체와 부분의 생명 주기가 독립적이며, 약한 소유 관계를 의미
- 전체 객체가 소멸될 때 부분 객체는 독립적으로 존재할 수 있음
// 부분 객체
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 = [];
void addEmployee(Employee emp) {
employees.add(emp);
}
void displayDepartmentInfo() {
print('부서 이름 : ${deptName}');
for (var emp in employees) {
emp.displayEmployeeInfo();
}
}
}
void main() {
// 부분 객체는 전체 객체와 독립적으로 존재 가능
Department dept1 = Department('개발 부서');
Department dept2 = Department('디자인 부서');
Employee emp1 = Employee('홍길동');
Employee emp2 = Employee('김철수');
Employee emp3 = Employee('김유신');
dept1.addEmployee(emp1);
dept1.addEmployee(emp2);
dept2.addEmployee(emp3);
dept1.displayDepartmentInfo();
dept2.displayDepartmentInfo();
}
Ⅱ Mixin
01. Mixin이란?
Mixin이란?
- Mixin은 Dart에서 클래스 간의 코드를 재사용하기 위한 매커니즘, 일족의 코드 조각
- Mixin은 다중 상속의 문제를 해결할 수 있으며, 컴퍼지션을 사용하지 않고 여러 클래스의 기능을 공유할 수 있음
Mixin의 필요성
- Java에서 하나의 클래스는 오직 하나의 클래스만 상속할 수 있는 단일 상속만 허용
- 대신 interface를 통해 다중 구현이 가능하지만, 메서드의 구체적인 구현이 제한됨
- Mixin을 활용하면 다중 상속 문제를 해결하고, 다른 클래스의 기능을 재사용 가능
with 키워드
- Mixin을 클래스에 주입할 때 사용하는 키워드
- 다른 클래스의 코드를 상속 없이 재사용하기 위해 사용
- 만약 Mixin 주입 과정에서 코드 충돌이 발생할 경우 마지막에 주입된 Mixin의 메서드를 적용
mixin Engine {
int power = 5000;
}
mixin Wheel {
String wheelName = '4륜 구동 바퀴';
}
class BMW with Engine, Wheel {}
void main() {
// BMW 객체 인스턴스화
BMW bmw1 = BMW();
// BMW 클래스에는 power과 wheelName 속성이 정의되어 있지 않지만,
// mixin을 통해 상속받은 속성을 참조 가능
print('bmw1 power : ${bmw1.power}');
print('bmw1 wheelName : ${bmw1.wheelName}');
Wheel wheel1 = Wheel(); // 에러 - Mixin은 인스턴스화 불가능
}
02. Mixin 인스턴스화
Mixin 인스턴스화
- 기본적으로 Mixin은 클래스가 아닌 코드 조각에 가까워, 독립적으로 인스턴스화를 할 수 없음
- 컴파일 과정에서 주입되는 class로 병합되어 하나의 인스턴스가 됨
- Mixin은 생성자를 정의할 수 없으며, 독립적인 객체로 존재할 수 없음
Mixin class
- Mixin class는 Mixin을 독립적으로 인스턴스화할 수 있게 함
- Mixin class는 Mixin의 성질과 class의 성질을 모두 가지고 있음
Mixin | Class | mixin class | |
인스턴스화 | 불가능 | 가능 | 가능 |
다중 상속 | 가능 | 불가능 | 가능 |
생성자 정의 | 불가능 | 가능 | 불가능 |
mixin class Engine {
int power = 3000;
}
mixin class Wheel {
String wheelName = '4륜 구동 바퀴';
}
class BMW with Engine, Wheel {}
void main() {
BMW bmw1 = BMW();
print('bmw1 power : ${bmw1.power}');
print('bmw1 wheelName : ${bmw1.wheelName}');
// Mixin Class는 독립적으로 인스턴스화 가능
Engine engine = Engine();
Wheel wheel = Wheel();
print('engine : ${engine.power}');
print('wheel : ${wheel.wheelName}');
}
Ⅲ 추상 클래스
01. 추상 클래스란?
추상 클래스란?
- 추상 클래스는 완전한 구현들을 제공하지 않는 클래스
- 상속을 통해 다른 클래스가 이를 확장하여, 구체적인 동작을 구현하도록 강제할 수 있는 클래스
- 추상 클래스는 조금 더 일반화적인 개념을 표현하며, 공통된 속성과 메서드를 정의하는데 많이 활용
- 추상 클래스는 메서드 구현부가 없으며, 인스턴스화 시킬 수 없음
02. 추상 클래스로의 코드 발전 과정
1) 동물 소리가 나는 일반 클래스 생성
class Dog {
void performAction() {
print('멍멍 배고파');
}
}
class Cat {
void performAction() {
print('야옹 배고파');
}
}
void main() {
Dog dog = Dog();
Cat cat = Cat();
dog.performAction();
cat.performAction();
}
2) 물고기 클래스 추가
class Dog {
void performAction() {
print('멍멍 배고파');
}
}
class Cat {
void performAction() {
print('야옹 배고파');
}
}
class Fish {
void hungry() {
print('뻐끔 배고파');
}
}
void main() {
Dog dog = Dog();
Cat cat = Cat();
dog.performAction();
cat.performAction();
Fish fish = Fish();
fish.hungry();
// 기능은 정상적으로 작동하지만 공통된 행위를 하는 메서드의 이름이 다름
fish.performAction(); // 만약 동적인 코드였다면 오류 발생
}
3) Animal 추상 클래스를 구현
abstract class Animal {
void performAction();
}
class Dog implements Animal {
@override
void performAction() {
print('멍멍 배고파');
}
}
class Cat implements Animal {
@override
void performAction() {
print('야옹 배고파');
}
}
class Fish implements Animal {
@override
void performAction() {
print('뻐끔 배고파');
}
}
void main() {
Dog dog = Dog();
Cat cat = Cat();
dog.performAction();
cat.performAction();
Fish fish = Fish();
fish.performAction();
// 공통된 행위를 하는 메서드를 추상 클래스에서 정의했기 때문에
// 이를 구현하는 클래스들은 공통된 행위를 구현하기 위해 같은 이름의 메서드를 사용
}
4) 동적 바인딩
void start(Animal name) {
// 어떤 동물이 동적으로 전달되더라도 performAction()이 호출되게 설계
name.performAction();
}
void main() {
Dog dog = Dog();
Cat cat = Cat();
dog.performAction();
cat.performAction();
Fish fish = Fish();
fish.performAction();
// 동적 바인딩
start(Dog());
start(Cat());
start(Fish());
}
'Programming > Flutter' 카테고리의 다른 글
[Flutter] Flutter 기초 #02 - Flutter 기본 위젯 (0) | 2025.01.09 |
---|---|
[Flutter] Flutter 기초 #01 - UI 디자인 원리 & 선언적 UI 구성 (0) | 2025.01.08 |
[Flutter] Dart 언어 기본 문법 #05 - 상속과 super 키워드 (0) | 2025.01.06 |
[Flutter] Dart 언어 기본 문법 #04 - Null Safety (0) | 2025.01.06 |
[Flutter] Dart 언어 기본 문법 #03 - 클래스와 인스턴스 (0) | 2025.01.03 |