본문 바로가기
Flutter

[Flutter 17] Dart Mixin과 Java 관계 개념 정리

by JINJINC 2025. 1. 7.
728x90
반응형

Java 객체 간의 관계 개념

Java는 단일 상속만 허용합니다.
(최상위 클래스인 Object를 제외한 모든 클래스는 하나의 부모 클래스만 상속 가능)

1. 연관 관계

  • 객체들이 서로 연결된 일반적인 관계를 의미합니다.

2. 컴포지션 관계 (Composition)

  • 정의:
    부분-전체 관계 중에서 생명주기가 밀접히 연관된 강한 소유 관계입니다.
  • 특징:
    • 전체 객체가 소멸되면 부분 객체도 함께 소멸됩니다.
    • 의존성이 매우 높습니다.
  • 예시:
    자동차(전체)와 엔진(부분) 관계
class Engine {
  final String type;
  Engine(this.type);

  void startEngine() {
    print('${type} 엔진이 시동됩니다.');
  }
}

class Car {
  final Engine engine;

  Car(String enginType) : engine = Engine(enginType) {
    print('생성자 호출시 내부 스택 메모리가 호출 된다.');
  }

  void startCar() {
    engine.startEngine();
    print('차가 출발합니다.');
  }
}

void main() {
  Car car1 = Car('v8');
  car1.startCar();
}

3. 집합 관계 (Aggregation)

  • 정의:
    부분-전체 관계 중에서 전체와 부분의 생명주기가 독립적인 약한 소유 관계입니다.
  • 특징:
    • 전체 객체가 소멸되더라도 부분 객체는 독립적으로 존재할 수 있습니다.
  • 예시:
    부서(전체)와 직원(부분) 관계
class Employee {
  final String name;
  Employee(this.name);

  void displayEmployeeInfo() {
    print('직원의 이름 : ${name}');
  }
}

class Department {
  final String deptName;
  List<Employee> employees;

  Department(this.deptName) : employees = [] {
    print('==Department 생성자 내부 스택 호출 ==');
  }

  void addEmployee(Employee emps) {
    employees.add(emps);
  }

  void addEmployees(List<Employee> emps) {
    for (var emp in emps) {
      employees.add(emp);
    }
  }

  void displayDepartmentInfo() {
    print('==================');
    print('부서의 이름 : ${deptName}');
    for (var emp in employees) {
      emp.displayEmployeeInfo();
    }
    print('==================');
  }
}

void main() {
  Department department1 = Department("개발부");
  Department department2 = Department("디자인부");

  Employee emp1 = Employee('홍길동');
  Employee emp2 = Employee('김유신');
  Employee emp3 = Employee('야스오');

  List<Employee> emps = [emp1, emp2];
  department2.addEmployee(emp3);
  department1.addEmployees(emps);

  department1.displayDepartmentInfo();
  department2.displayDepartmentInfo();
}
==Department 생성자 내부 스택 호출 ==
==Department 생성자 내부 스택 호출 ==
==================
부서의 이름 : 개발부
직원의 이름 : 홍길동
직원의 이름 : 김유신
==================
==================
부서의 이름 : 디자인부
직원의 이름 : 야스오
==================

설명:

  • Department 객체는 List<Employee>를 사용하여 여러 직원을 관리합니다.
  • 부서 객체가 소멸되더라도 직원 객체는 독립적으로 존재할 수 있습니다.
  • 부서 이름과 직원 정보를 출력하는 기능을 제공합니다.

 

4. 이니셜라이저 리스트

이니셜라이저 리스트(:)는 생성자 호출 시, 클래스 필드의 초기화 작업을 수행하기 위해 사용됩니다.
특히, 클래스 필드가 final일 경우, 생성자 바디보다 먼저 초기화해야 하므로 이니셜라이저 리스트가 유용합니다.

장점

  • 생성자의 실행 이전에 필드를 초기화할 수 있습니다.
  • 상속 관계뿐만 아니라, 컴포지션 및 집합 관계에서도 객체 생성 시 유용합니다.

 

Dart의 Mixin

  • 정의
    Mixin은 클래스의 코드를 여러 클래스 계층에서 재사용할 수 있도록 도와주는 코드 조각입니다.
  • 특징
    1. 다중 상속의 문제를 해결합니다.
    2. 컴퍼지션을 사용하지 않고도 다른 클래스의 코드를 재사용할 수 있습니다.
    3. Dart에서 Mixin은 with 키워드를 사용하여 적용합니다.
  • 장점
    • 코드 중복을 줄이고 유지보수를 용이하게 합니다.
    • 특정 기능을 재사용하거나 추가할 때 유연성을 제공합니다.
  • 예시 (Dart Mixin 사용):
mixin Flyable {
  void fly() => print("날아다닐 수 있음!");
}

mixin Swimmable {
  void swim() => print("수영할 수 있음!");
}

class Bird with Flyable {}

class Fish with Swimmable {}

void main() {
  Bird bird = Bird();
  bird.fly();

  Fish fish = Fish();
  fish.swim();
}

Dart와 Java 개념 비교

개념Dart (Mixin)Java (컴포지션/집합)

다중 상속 가능 (with 키워드 사용) 불가능 (단일 상속만 허용)
코드 재사용 코드 재사용에 매우 적합 상속 외에 컴포지션 및 인터페이스 사용
소유 관계 관계 개념이 없고, 단순 코드 조각 재사용에 집중 강한 소유 관계(컴포지션) 또는 약한 소유 관계(집합)으로 정의

 

 

 

Dart에서 Mixin과 Mixin Class 사용하기

Dart에서 Mixin은 여러 계층에서 코드를 재사용할 수 있도록 도와주는 강력한 도구입니다. 이번 글에서는 MixinMixin Class를 사용한 사례를 통해 이를 효과적으로 활용하는 방법을 정리하겠습니다.


1. Mixin의 개념

Mixin이란?

  • 클래스 간의 코드 재사용을 가능하게 해주는 코드 조각.
  • 다중 상속을 지원하지 않는 Dart에서 다중 상속의 대안을 제공합니다.
  • with 키워드를 사용하여 Mixin을 클래스에 추가합니다.

Mixin의 특징

  1. 다중 상속 문제 해결: 단일 상속만 허용하는 Dart에서 코드 조각을 여러 클래스에서 공유할 수 있습니다.
  2. 코드 재사용: 공통된 기능을 Mixin으로 정의하고, 필요한 클래스에서 가져다 사용할 수 있습니다.
  3. 독립성: Mixin은 독립된 기능 단위로 설계되어 다른 클래스와 강하게 결합되지 않습니다.
  4. 인스턴스화 불가: Mixin 자체는 인스턴스화할 수 없습니다.

2. 기본 Mixin 사용 예제

mixin Engine {
  int power = 5000;
}

mixin Wheel {
  String wheelName = '4륜구동 바퀴';
}

// Mixin 적용: with 키워드 사용
class BMW with Engine, Wheel {
  final String engineType;

  BMW(this.engineType) {
    // 조건에 따라 power 값 설정
    if (engineType == 'V8') {
      power = 8000;
    } else if (engineType == 'V6') {
      power = 6000;
    } else {
      power = 5000; // 기본 값
    }
  }

  void display() {
    print('BMW $engineType');
    print('Power: $power');
    print('Wheel: $wheelName');
  }
}

void main() {
  BMW bmw1 = BMW('V8');
  print(bmw1.power); // 8000
  print(bmw1.wheelName); // 4륜구동 바퀴

  bmw1.display();
}

 

 

출력

8000
4륜구동 바퀴
BMW V8
Power: 8000
Wheel: 4륜구동 바퀴

설명

  • Engine과 Wheel Mixin은 BMW 클래스에 기능을 추가합니다.
  • with 키워드를 사용하여 Mixin을 클래스에 적용합니다.
  • Mixin은 독립적인 코드 조각으로, 클래스를 설계할 때 필요한 기능만 가져와 사용할 수 있습니다.

3. Mixin의 한계: 인스턴스화 불가

Mixin은 독립적으로 인스턴스화할 수 없습니다.

 

void main() {
  // Mixin 자체는 인스턴스화 불가
  // Wheel wheel = Wheel(); // 오류 발생
}

해결 방법: Mixin Class

Dart 3.0부터 **mixin class**를 도입하여 Mixin을 인스턴스화할 수 있도록 확장된 기능을 제공합니다.


4. Mixin Class 사용 예제

 

mixin class Engine {
  int power = 5000;

  void startEngine() {
    print('엔진 시동: $power 마력');
  }
}

mixin class Wheel {
  String wheelName = '사륜구동바퀴';

  void rotateWheels() {
    print('$wheelName가 회전합니다.');
  }
}

class BMW with Engine, Wheel {}

void main() {
  // Mixin Class는 인스턴스화 가능
  Engine e = Engine();
  Wheel w = Wheel();

  e.startEngine(); // 엔진 시동: 5000 마력
  w.rotateWheels(); // 사륜구동바퀴가 회전합니다.

  // BMW 클래스에서도 Mixin 기능 사용
  BMW bmw = BMW();
  bmw.startEngine(); // 엔진 시동: 5000 마력
  print(bmw.wheelName); // 사륜구동바퀴
}

 

출력

엔진 시동: 5000 마력
사륜구동바퀴가 회전합니다.
엔진 시동: 5000 마력
사륜구동바퀴

5. Mixin과 Mixin Class 비교

특징MixinMixin Class

인스턴스화 가능 여부 불가능 가능
기능 추가 클래스에 코드 조각 추가 클래스에 코드 조각 추가 및 독립적 사용 가능
사용법 with 키워드 사용 with 키워드 사용 + 인스턴스화 가능
Dart 버전 모든 버전에서 사용 가능 Dart 3.0 이상

6. 요약

  • Mixin은 코드 재사용을 위해 사용되며, with 키워드를 통해 클래스로 가져올 수 있습니다.
  • Mixin은 독립적으로 인스턴스화할 수 없지만, **mixin class**를 사용하면 이를 해결할 수 있습니다.
  • Mixin Class는 인스턴스화 가능하고, 여전히 다른 클래스에 기능을 추가하는 역할도 수행합니다.
  • Dart에서 Mixin을 활용하면 유연한 코드 설계와 유지보수가 용이한 구조를 만들 수 있습니다.

Mixin과 Mixin Class를 활용하여 더 효율적이고 확장 가능한 Dart 프로그램을 설계해보세요! 😊

728x90
반응형

댓글