openplanning

Mixins trong Dart

  1. Từ khoá "with"
  2. Từ khoá "on"
  3. Thi hành interface
Mixin là cách định nghĩa mã, thứ có thể được tái sử dụng trong nhiều lớp. Nói cách khác một lớp có thể xát nhập một hoặc nhiều Mixin vào để trở thành một phần của nó.
Về cơ bản Mixin là một nhóm bao gồm các phương thức và các thuộc tính. Nó thúc đẩy nguyên tắc DRY (Don’t Repeat Yourself). DRY khuyên bạn theo đuổi phong cách lập trình thực dụng, nghĩa là viết code ngắn gọn và tránh lặp lại code một cách không cần thiết.
Các đặc điểm của Mixin:
  • Mixin có thể thực thi một hoặc nhiều interface.
  • Mixin không thể được khởi tạo. Bạn không thể tạo đối tượng của Mixin.
  • Sử dụng Mixin để chia sẻ mã giữa nhiều lớp.
  • Mixin không có Constructor và không thể mở rộng.
  • Có thể sử dụng nhiều Mixin trong một lớp.

1. Từ khoá "with"

Sử dụng từ khoá "mixin" để định nghĩa một Mixin. Và sử dụng từ khoá "with" để sáp nhập một hoặc nhiều Mixin(s) vào một lớp.
mixin Mixin1{
  // code
}

mixin Mixin2{
  // code
}

class ClassName with Mixin1, Mixin2{
  // code
}
Ví dụ:
mixin_ex1.dart
mixin CanFly {
  void fly() {
    print('I can fly');
  }
}

mixin CanWalk {
  void walk() {
    print('I can walk');
  }
}

class Bird with CanFly, CanWalk {}

class Human with CanWalk {}

void main() {
  var bird = Bird();
  print('--- Bird ---');
  bird.fly();
  bird.walk();

  print('--- Human ---');
  var human = Human();
  human.walk();
}
Output:
--- Bird ---
I can fly
I can walk
--- Human ---
I can walk
Ví dụ:
mixin_ex2.dart
mixin Counter {
  int _counter = 0;
  int next() => ++_counter;
}

class Operation {
  void operate(int step) {
    print("Do Step: $step");
  }
}

class $OperationWithCounter = Operation with Counter;

class AutoStepOperation extends $OperationWithCounter {
  void operate([int? step]) {
    super.operate(step ?? super.next());
  }
}

void main() {
  var obj = AutoStepOperation();

  obj.operate(10);
  obj.operate();
  obj.operate();
}
Output:
Do Step: 10
Do Step: 1
Do Step: 2

2. Từ khoá "on"

Trong một vài trường hợp bạn muốn định nghĩa một Mixin chỉ để sử dụng cho một "kiểu (lớp)" cụ thể bạn có thể sử dụng từ khoá "on":
Ví dụ: Định nghĩa một Mixin chỉ có thể được sử dụng bởi một lớp cụ thể hoặc các lớp con của nó.
minix_on_ex1.dart
abstract class Animal {
  void move() {
    print("I am moving..");
  }
}

mixin CanRun on Animal {
  void run() {
    print("I am running");
  }
}

class Cat extends Animal with CanRun {}

// Error (Tree is not subclass of Animal)
// class Tree with CanRun{}

void main() {
  var tom = Cat();

  tom.move();
  tom.run();
}

3. Thi hành interface

Mixin có thể thi hành (implements) một hoặc nhiều interface.
minix_itf_ex1.dart
abstract class CanFly {
  void fly();
}

class CanMove {
  void run() {
    print("I am running");
  }

  void walk() {
    print("I am walking");
  }
}

mixin CanMoveAndFly implements CanFly, CanMove {
  void fly() {
    print("I'm flying");
  }

  void run() {
    print("I'm running");
  }

  void walk() {
    print("I'm walking");
  }
}

class FlappyBird with CanMoveAndFly {}

void main() {
  var fbird = FlappyBird();

  fbird.fly();
  fbird.run();
  fbird.walk();
}
Output:
I'm flying
I'm running
I'm walking
Mixin sẽ là trừu tượng (abstract) nếu nó không thực hiện tất cả các phương thức trong các intereface. Tuy nhiên bạn không cần sử dụng từ khoá "abstract" đối với Mixin.
mixin_itf_ex2.dart
abstract class CanFly {
  void fly();
}

class CanMove {
  void run() {
    print("I am running");
  }

  void walk() {
    print("I am walking");
  }
}

// Abstract Mixin
mixin CanMoveAndFly implements CanFly, CanMove {
  void fly() {
    print("I'm flying");
  }
  // run(), walk() will be implemented in the class using this Mixin.
}

class FlappyBird with CanMoveAndFly {
  @override
  void run() {
    print("FlappyBird is flying");
  }

  @override
  void walk() {
    print("FlappyBird is walking");
  }
}

void main() {
  var fbird = FlappyBird();

  fbird.fly();
  fbird.run();
  fbird.walk();
}
Output:
I'm flying
FlappyBird is flying
FlappyBird is walking