프로그래밍 언어/Dart

Dart에서 믹스인과 익스텐션 사용법: 다중 상속과의 차이점 - Dart 기초 #12

eco7T 2024. 6. 14. 08:33
반응형

이번 글은 Dart 언어의 믹스인(Mixin)과 익스텐션(Extension)에 대한 개념과 사용법을 설명합니다. Dart 프로그램 작성에 있어서 믹스인과 익스텐션의 차이점을 이해하고, 이를 실제 코드에 적용할 수 있도록 예시와 함께 정리해 보았습니다. 특히, 상속과 믹스인의 차이점을 명확히 하고, 다중 상속과 다중 믹스인의 개념을 비교하여 코드 재사용성을 높일 수 있는 방법에 대해 다시 한번 생각해 볼 수 있었으면 합니다.

Dart에서 믹스인과 익스텐션 사용법
Dart에서 믹스인과 익스텐션 사용법

 

Dart 믹스인(Mixin) 과 익스텐션(Extension)

1. 믹스인(Mixin)

믹스인은 여러 클래스 계층에서 클래스의 코드를 재사용하는 방법 중 하나입니다. 상속과는 달리 믹스인은 클래스의 일부 기능만을 가져와서 사용할 수 있습니다. 즉, 상속처럼 클래스 전체를 물려받는 게 아니라 필요한 기능만 가져와서 사용하는 것이죠. 믹스인과 상속의 차이점은 본 글 맨 아래에 따로 설명을 추가했습니다.

반응형

Dart에서는  with  키워드를 사용하여 믹스인을 구현합니다. 믹스인으로 사용될 클래스는 일반 클래스와 달리 생성자를 가질 수 없습니다.

 

  예시 코드

mixin Flyable { void fly() { print('I can fly!'); } } class Bird with Flyable { // ... } class Airplane with Flyable { // ... } void main() { Bird bird = Bird(); bird.fly(); // 출력: I can fly! Airplane plane = Airplane(); plane.fly(); // 출력: I can fly! }

위 예제에서는  Flyable 이라는 믹스인을 정의하고,  Bird 와  Airplane 클래스에서  with 키워드를 사용하여  Flyable 믹스인을 가져와 사용하고 있습니다. 이렇게 하면  Bird 와  Airplane 클래스 모두  fly() 메서드를 사용할 수 있게 됩니다.

2. 익스텐션(Extension)

익스텐션은 기존 라이브러리의 소스 코드를 수정하지 않고도 클래스, 열거형, 구조체 등의 기능을 확장할 수 있는 기능입니다. 익스텐션을 사용하면 기존 타입에 새로운 기능을 추가할 수 있습니다.

 

Dart에서는  extension 키워드를 사용하여 익스텐션을 정의합니다.

 

  예시 코드

extension StringExtension on String { String reverse() { return this.split('').reversed.join(); } } void main() { String str = 'Hello, world!'; print(str.reverse()); // 출력: !dlrow ,olleH }

위 예제에서는  String 클래스에  reverse() 메서드를 추가하는 익스텐션을 정의하고 있습니다. 이렇게 하면  String 타입의 변수에서  reverse() 메서드를 호출하여 문자열을 뒤집을 수 있게 됩니다.

 

익스텐션은 기존 타입의 기능을 확장할 때 유용하게 사용할 수 있습니다. 하지만 너무 많은 익스텐션을 사용하면 코드의 가독성이 떨어질 수 있으므로 주의해서 사용해야 합니다.

3. 믹스인과 익스텐션 비교

믹스인과 익스텐션은 모두 기존 클래스의 기능을 확장하는 데 사용됩니다. 하지만 둘 사이에는 몇 가지 차이점이 있습니다.

  • 믹스인은 클래스에서 재사용 가능한 코드를 캡슐화하는 데 사용되는 반면, 익스텐션은 기존 타입에 새로운 기능을 추가하는 데 사용됩니다.
  • 믹스인은  with 키워드를 사용하여 클래스에 포함되는 반면, 익스텐션은  extension 키워드를 사용하여 별도로 정의됩니다.
  • 믹스인은 상속과 비슷한 방식으로 동작하지만, 다중 상속을 지원하지 않는 Dart에서 유용하게 사용될 수 있습니다. 반면 익스텐션은 기존 타입의 기능을 확장하는 데 초점을 맞추고 있습니다.

 

4. 클래스 상속과 믹스인의 차이점

상속은 부모-자식 관계를 나타내는 개념입니다.

자식 클래스는 부모 클래스의 모든 특성을 물려받습니다. 이는 마치 부모의 유전자를 물려받는 것과 비슷합니다. 예를 들어, "스포츠카는 자동차의 한 종류이다"라고 할 수 있습니다. 이 경우 스포츠카는 자동차의 모든 특성을 가지고 있으면서도 자신만의 독특한 특성을 추가로 가질 수 있습니다.

 

반면 믹스인은 클래스에 레고 블록처럼 기능을 추가하는 개념입니다.

믹스인은 독립적인 기능 모듈이라고 생각할 수 있습니다. 예를 들어, "스포츠카는 터보 엔진이라는 기능을 가지고 있다"라고 할 수 있습니다. 이 경우 터보 엔진은 스포츠카의 본질적인 특성이 아니라 추가된 기능입니다. 이 기능은 다른 종류의 자동차에도 추가될 수 있습니다.

 

다시 말해, 상속은 "~은 ~이다(is-a)"라는 관계를 나타내고, 믹스인은 "~은 ~을 가지고 있다(has-a)"라는 관계를 나타냅니다.

상속과 믹스인의 차이점을 식당에 비유해 보겠습니다.

  • 상속: 한식당은 음식점입니다. 한식당은 음식점이 가진 모든 특성(음식을 제공한다, 테이블과 의자가 있다 등)을 물려받습니다. 동시에 한식당은 한식이라는 독특한 특성을 가지고 있습니다.
  • 믹스인: 한식당은 배달 서비스를 제공합니다. 배달 서비스는 한식당의 본질적인 특성이 아니라 추가된 기능입니다. 이 기능은 다른 종류의 음식점(예: 피자집, 중국집)에도 추가될 수 있습니다.

이 비유를 통해 상속은 "한식당은 음식점이다"라는 관계를, 믹스인은 "한식당은 배달 서비스를 가지고 있다"라는 관계를 나타낸다는 것을 이해할 수 있습니다.

 

다중 상속과 다중 믹스인의 차이

  • 다중 상속: 많은 프로그래밍 언어에서 다중 상속을 지원하지 않습니다. 다중 상속은 복잡성을 증가시키고 모호성을 야기할 수 있기 때문입니다. Dart에서도 다중 상속을 지원하지 않습니다.
  • 다중 믹스인: 믹스인은 여러 개를 동시에 사용할 수 있습니다. 이를 통해 다중 상속의 이점을 얻을 수 있으면서도 복잡성과 모호성을 피할 수 있습니다.

생성자 상속 여부

  • 상속: 자식 클래스는 부모 클래스의 생성자를 상속받습니다. 자식 클래스의 생성자에서 부모 클래스의 생성자를 호출해야 합니다.
  • 믹스인: 믹스인은 생성자를 가질 수 없습니다. 믹스인은 클래스의 기능을 확장하는 데 초점을 맞추기 때문에 생성자를 상속받을 필요가 없습니다.

  다음은 상속과 믹스인의 차이점을 보여주는 예시 코드입니다.

// 상속 예시 class Vehicle { void move() { print('움직입니다.'); } } class Car extends Vehicle { void honk() { print('빵빵!'); } } // 믹스인 예시 mixin Engineered { void startEngine() { print('엔진을 시동합니다.'); } } class Car with Engineered { // ... }

위의 예제에서  Car 클래스는  Vehicle 클래스를 상속받아서 "is-a" 관계를 나타내고 있습니다. 반면에  Car 클래스는  Engineered 믹스인을 사용하여 "has-a" 관계를 나타내고 있습니다.

 

상속과 믹스인은 모두 코드 재사용과 기능 확장을 위해 사용되지만, 사용 목적과 방식에 차이가 있습니다. 상황에 따라 적절한 방법을 선택하여 사용하는 것이 좋습니다.

반응형