web analytics

Dart : รู้จักกับ Mixin ในภาษา Dart

cover

สวัสดีครับ วันนี้มาลองเล่นอะไรที่น่าสนใจในเรื่องของภาษา dart ที่ใช้ใน Flutter กัน หนึ่งในนั้นคือ keyword  เช่น with และ mixin ในตอนที่ผมหัดเขียน Flutter แรกๆ ผมยังไม่เข้าใจว่ามันคืออะไร ก็ได้ลองต้องค้นหาคำตอบ ดังนั้นในบล็อกนี้ผมจะขอสรุปและอธิบายสั้นๆเกี่ยกับ mixin ในภาษา Dart ครับ

 

รู้จักกับ Mixin

สิ่งนึงในหลายๆภาษา เช่น Java ไม่สนับสนุน การสืบทอดแบบหลาย (Multiple Inheriance) โดยตรง ซึ่งจะสามารถสืบทอดได้เพียง class เดียวเท่านั้น ทำให้หากต้องการทำ Multiple Inheritance จริงๆจำเป็นต้องไปใช้วิธีอื่นมาช่วย เช่น interface , composit แทน และในภาษา Dart ก็ใช้แนวทางนี้เช่นกัน คือ สามารถสืบทอดได้เพียง class เดียว แต่ทว่า Dart มองว่าการใช้ interface แบบใน Java เพื่อพยายามสร้างสิ่งที่คล้ายกับ Multiple Inheritance นั้น ไม่ทำให้ code อ่านง่ายอย่างที่ควรจะเป็น ใน Dart จึงใช้วิธีการที่เรียกว่า mixin เพื่อให้การทำใช้งานง่ายและดูสะอาดขึ้น

การใช้ mixin นั้นง่ายมาก คือ สร้าง class หรือ abstract class ที่ต้องการให้เป็น Parent ก่อน

abstract class PersonA
{
  String name;
  speak() {
    print("I'm A");
  }
}

 class PersonB{
  int age;
  speak() {
   print("I'm B");
  }
}

 class PersonC{
  bool single;
  speak() {
    print("I'm C");
  }
}

class Human {

  speak() {
    print("I'm Human");
  }
}

 

จากนั้นก็ใช้ keyword ว่า with ตามด้วย class ที่ต้องการให้ไปสืบทอด หากมีหลายอื่นคั้นด้วย , (comma)
เช่น class Man สืบทอดจาก Human , PersonA , PersonB , PersonC
และสามารถใช้ตัวแปรและ method จากทั้ง PersonA , PersonB , PersonC ได้

class Man extends Human with PersonA, PersonB, PersonC {
  say() {
    print(name);
    print(age);
    print(single);
  }
}

 

ซึ่ง class ที่สืบทอดด้วย mixin นี้ จะต้องไม่มีการสืบทอดจาก class อื่น

4

 

Mixin Keyword

เพื่อความชัดเจน Dart 2.1 เพิ่ม keyword คำว่า mixin โดยเฉพาะ โดย class ที่มี keyword นี้ จะใช้สำหรับการสืบทอดแบบ mixin เท่านั้น ต่างกับการใช้ class หรือ abstract class แบบเดิม เพราะ class โดยปกติ สามารถนำไปสร้าง instance ได้ หรือนำไปสืบทอดได้ ส่วน abstract class ก็สามารถนำไปสืบทอดจาก class ปกติได้ การใช้งาน keyword mixin จึงเป็นเหมือนระบุเฉพาะเจาะจงมากขึ้น ว่าสำหรับ mixin เท่านั้น

เช่น

mixin PersonA{}

class Human {}

class Man extends Human with PersonA {}

 

Overriding in Mixin

ในกรณีที่ มีตัวแปร หรือ method ซ้ำกันใน class ระหว่าง class ที่สืบทอดโดยตรงกับ การสืบทอดแบบ mixin กันเอง ทำให้เกิด override ผลคือจะใช้ mixin อันท้ายสุดเสมอ ก็คือ Mixin เป็น Top Level เสมอ

 

เช่น มี mixin 3 class ซึ่งมี method ตัวนึง คือ speak() จากนั้น class Man สืบทอด mixin จากทั้ง 3 class ทำให้ speak() ทับซ้อนกัน

mixin PersonA{
   speak() {
      print("I'm A");
   }
}

mixin PersonB{
   speak() {
      print("I'm B");
   }
}

mixin PersonC{
   speak() {
      print("I'm C");
   }
}

class Human {
  speak() {
    print("I'm Human");
  }
}

class Man extends Human with PersonA, PersonB, PersonC {
  say() {
    speak();
  }
}

 

เมื่อเราเรียก speak() การทำงานจะใช้ speak() ของ class ไหน?

Man man = Man();
man.say();

 

คำตอบคือ class PersonC เพราะ PersonC คือ class Mixin ตัวสุดท้ายหรือหลังสุด ที่ใส่ให้ Man นั่นเอง

1

 

แม้ว่าเราจะเรียก super.speak(); มันก็ยังจะเรียก จาก PersonC เพราะ speak() ได้ override ทับทุก class แม้แต่ Human ที่สืบทอดแบบ extens โดยตรงก็ตาม

class Man extends Human with PersonA, PersonB, PersonC {
  say() {
    super.speak();
    speak();
  }
}

2

 

“on” Keyword

Mixin ก็สามารถสืบทอดกันเองได้ด้วย โดยเพิ่ม keyword ว่า on ตามด้วย ชื่อ class ได้
เช่น

...

mixin PersonC on PersonB {
  speak() {
    super.speak();
    print(age);
    print("I'm C");
  }
}

class Man extends Human with PersonA, PersonB, PersonC {
  say() {
    speak();
  }
}

3

 

สรุป

Mixin เป็นความสามารถนึงของภาษา Dart ที่มาช่วยการทำ Multiple Inheritance ได้ง่ายขึ้นนั่นเอง ซึ่งไม่จำเป็นต้องใช้ keyword mixin ก็ได้ สามารถใช้ abstract class , class แต่เพื่อความเฉพาะเจาะจงว่าเป็น mixin ที่ไม่สามารถนำไปใช้แบบ class หรือ abstract class ได้ ก็สามารถใช้ keyword ว่า mixin แทนนั่นเอง

 

Credit
https://medium.com/flutter-community/dart-what-are-mixins-3a72344011f3