อะไรคือความแตกต่างระหว่าง Mixin และการถ่ายทอดทางพันธุกรรม?
อะไรคือความแตกต่างระหว่าง Mixin และการถ่ายทอดทางพันธุกรรม?
คำตอบ:
โดยทั่วไปแล้ว mixin จะใช้กับการสืบทอดหลายรายการ ดังนั้นในแง่นั้น "ไม่มีความแตกต่าง"
รายละเอียดคือมิกซ์อินแทบไม่มีประโยชน์ในฐานะออบเจ็กต์แบบสแตนด์อโลน
ตัวอย่างเช่นสมมติว่าคุณมี mixin ชื่อ "ColorAndDimension" ซึ่งจะเพิ่มคุณสมบัติสีและความกว้างและความสูง
ตอนนี้คุณสามารถเพิ่ม ColorAndDimension ให้กับ a พูดคลาส Shape คลาส Sprite คลาส Car และอื่น ๆ และทั้งหมดนี้จะมีอินเทอร์เฟซเดียวกัน (พูดว่า get / setColor, get / setHeight / Width ฯลฯ )
ดังนั้นในกรณีทั่วไปการถ่ายทอดทางพันธุกรรมของมิกซ์อิน แต่คุณสามารถโต้แย้งได้ว่ามันเป็นเรื่องของบทบาทของคลาสในโดเมนโดยรวมว่ามิกซ์อินเป็นคลาส "หลัก" หรือเพียงแค่มิกซ์อิน
แก้ไข - เพียงเพื่อชี้แจง
ใช่มิกซ์อินถือได้ว่าเป็นอินเทอร์เฟซที่มีการใช้งานที่เกี่ยวข้อง จริงๆแล้วมันเป็นเพียงการถ่ายทอดทางพันธุกรรมแบบเก่า ๆ ในชีวิตประจำวันโดยใช้คลาสธรรมดา ๆ ในชีวิตประจำวัน มันเป็นเพียงแอปพลิเคชั่นเฉพาะของ MI ภาษาส่วนใหญ่ไม่ได้ให้สถานะพิเศษใด ๆ เป็นเพียงคลาสที่ออกแบบมาให้ "ผสมกัน" แทนที่จะใช้แบบสแตนด์อโลน
อะไรคือความแตกต่างระหว่าง Mixin และการถ่ายทอดทางพันธุกรรม?
ผสมในเป็นชั้นฐานคุณสามารถรับมรดกจากเพื่อให้การทำงานเพิ่มเติม ตัวอย่าง Pseudocode:
class Mixin:
def complex_method(self):
return complex_functionality(self)
ชื่อ "mix-in" แสดงว่ามีวัตถุประสงค์เพื่อผสมกับรหัสอื่น ๆ ดังนั้นการอนุมานก็คือคุณจะไม่สร้างอินสแตนซ์คลาสมิกซ์อินด้วยตัวมันเอง อ็อบเจ็กต์ต่อไปนี้ไม่มีข้อมูลและไม่มีเหตุผลที่จะสร้างอินสแตนซ์ให้เรียก complex_method (คุณสามารถกำหนดฟังก์ชันแทนคลาสได้เช่นกัน)
>>> obj = Mixin()
บ่อยครั้งที่การมิกซ์อินถูกใช้กับคลาสพื้นฐานอื่น ๆ
ดังนั้นมิกซ์อินจึงเป็นส่วนย่อยหรือกรณีพิเศษของการถ่ายทอดทางพันธุกรรม
ข้อดีของการใช้ mix-in over single inheritance คือคุณสามารถเขียนโค้ดสำหรับฟังก์ชันการทำงานได้ครั้งเดียวจากนั้นใช้ฟังก์ชันเดียวกันในคลาสต่างๆ ข้อเสียคือคุณอาจต้องมองหาฟังก์ชันการทำงานนั้นในที่อื่นนอกเหนือจากที่ใช้งานดังนั้นจึงเป็นการดีที่จะลดข้อเสียนั้นโดยการเก็บไว้ใกล้ ๆ
ฉันพบว่ามีการผสมผสานที่จำเป็นในการใช้กับการสืบทอดเดียวโดยที่เรากำลังทดสอบรหัสที่คล้ายกันจำนวนมาก แต่กรณีทดสอบนั้นได้รับการสร้างอินสแตนซ์ตามการสืบทอดของกรณีพื้นฐานและวิธีเดียวที่จะทำให้รหัสปิด มือ (และในโมดูลเดียวกัน) โดยไม่ต้องยุ่งกับหมายเลขความครอบคลุมคือการสืบทอดจากออบเจ็กต์และให้เคสลูกสืบทอดจากฐานกรณีทดสอบสากลและฐานแบบกำหนดเองที่ใช้กับพวกมันเท่านั้น
ทั้งสองเป็นรูปแบบของคลาสแม่ที่ไม่ได้ตั้งใจให้เป็นอินสแตนซ์
mixinให้ฟังก์ชันการทำงาน แต่ไม่สามารถที่จะใช้มันโดยตรง ผู้ใช้มีวัตถุประสงค์เพื่อใช้ผ่านคลาส (ย่อย)
ชั้นฐานนามธรรมให้ติดต่อ แต่ไม่มีฟังก์ชั่นที่ใช้งานได้ ผู้ใช้มีวัตถุประสงค์เพื่อสร้างฟังก์ชันที่เรียกโดยอินเทอร์เฟซ
class Abstraction(metaclass=abc.ABCMeta):
@abc.abstractmethod
def complex_method(self):
return complex_functionality(self)
ที่นี่คุณถูกป้องกันไม่ให้สร้างอินสแตนซ์วัตถุนี้เนื่องจากต้องใช้คลาสย่อยในการใช้ฟังก์ชันด้วยวิธีการที่เป็นรูปธรรม (แม้ว่าคุณจะสามารถเข้าถึงฟังก์ชันภายในจากsuper()
):
>>> obj = Abstraction()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class Abstraction with
abstract methods complex_method
ใน Python บางคลาสในabc
โมดูลเป็นตัวอย่างของคลาสพาเรนต์ที่ทั้งสองมีฟังก์ชันการทำงานผ่านการสืบทอดและอินเทอร์เฟซนามธรรมที่คลาสย่อยต้องนำไปใช้ ความคิดเหล่านี้ไม่สามารถใช้ร่วมกันได้
พูดง่ายๆว่าการมิกซ์อินเป็นเพียงคลาสพื้นฐานที่คุณจะไม่สร้างอินสแตนซ์ด้วยตัวมันเองและโดยทั่วไปจะใช้เป็นคลาสฐานรองในการสืบทอดหลาย ๆ
การผสมผสานเป็นกรณีที่เฉพาะเจาะจงและ จำกัด ของการสืบทอด (หลายรายการ) ที่ใช้เพื่อวัตถุประสงค์ในการนำไปใช้งาน บางภาษา (เช่น Ruby) รองรับโดยไม่รองรับการสืบทอดหลาย ๆ
Mixin เป็นแนวคิดเชิงนามธรรมและอะไรก็ตามที่ตรงตามความต้องการถือได้ว่าเป็น mixin
นี่คือคำจำกัดความจาก Wikipedia
ในภาษาโปรแกรมเชิงวัตถุมิกซ์อินคือคลาสที่มีเมธอดสำหรับใช้โดยคลาสอื่นโดยไม่จำเป็นต้องเป็นคลาสพาเรนต์ของคลาสอื่น ๆ คลาสอื่น ๆ เหล่านั้นเข้าถึงเมธอดของ mixin ได้อย่างไรนั้นขึ้นอยู่กับภาษา บางครั้งมีการอธิบายว่ามิกซ์อินเป็น "รวม" มากกว่า "สืบทอด"
ในระยะสั้นความแตกต่างที่สำคัญจากการถ่ายทอดทางพันธุกรรมคือมิกซ์อินไม่จำเป็นต้องมีความสัมพันธ์แบบ "is-a" เหมือนการถ่ายทอดทางพันธุกรรม
จากมุมมองการนำไปใช้งานคุณสามารถคิดว่ามันเป็นอินเทอร์เฟซสำหรับการใช้งาน ตัวอย่างเช่นคลาสนามธรรมใน Java อาจถือได้ว่าเป็นมิกซ์อินหาก Java รองรับการสืบทอดหลายรายการ
"มิกซ์อินคือส่วนหนึ่งของคลาสในแง่ที่ตั้งใจจะแต่งกับคลาสอื่นหรือมิกซ์อิน" -DDJ
mixin เป็นส่วนของคลาสหรือโค้ดที่ไม่ได้มีไว้สำหรับการใช้งานแบบสแตนด์อโลน แต่คุณควรใช้มันในคลาสอื่นแทน ทั้งการเขียนเป็นเขตข้อมูลสมาชิก / ตัวแปรหรือเป็นส่วนรหัส ฉันมีความเสี่ยงมากที่สุดในภายหลัง ดีกว่าการคัดลอกโค้ดสำเร็จรูปเล็กน้อย
นี่เป็นบทความ DDJ ที่ดีที่แนะนำเรื่องนี้
Half-Life 2 / "Source" SDK เป็นตัวอย่างที่ดีของ C ++ mixins ในมาโครสภาพแวดล้อมนั้นจะกำหนดบล็อคโค้ดขนาดใหญ่ซึ่งสามารถเพิ่มเพื่อให้คลาสมี "รสชาติ" หรือคุณลักษณะเฉพาะ
ดูที่มาวิกิพีเดียเช่น: การเขียนตรรกะ Entity ในโค้ดตัวอย่างมาโคร DECLARE_CLASS ถือได้ว่าเป็นมิกซ์อิน ซอร์ส SDK ใช้มิกซ์อินอย่างกว้างขวางเพื่อสร้างมาตรฐานของโค้ดการเข้าถึงข้อมูลและกำหนดพฤติกรรมให้เอนทิตี
ด้วยการสืบทอดหลายชั้นคลาสใหม่อาจประกอบขึ้นจากซูเปอร์คลาสหลายคลาส คุณสามารถเรียกเฉพาะเมธอดที่กำหนดไว้ในซูเปอร์คลาส
ในทางกลับกัน mixin เป็นคลาสย่อยนามธรรมที่อาจใช้เพื่อสร้างความเชี่ยวชาญให้กับคลาสแม่ที่หลากหลาย Mixins อาจเรียกเมธอด (เช่นsayHello(): String
) แม้ว่าจะไม่ได้กำหนดวิธีการดังกล่าวก็ตาม
mixin M {
name: String
defmethod greetings() { print sayHello() + " " + name}
}
อย่างที่คุณเห็นคุณสามารถโทรsayHello()
ได้แม้ว่าจะไม่ได้กำหนดไว้ที่ใดก็ตาม ถ้าคุณเพิ่ม mixin M
ไปเรียนC
ที่C
ควรให้sayHello()
วิธีการ
ผมคิดว่ามันสำคัญที่จะต้องทราบว่าmixinไม่ได้หมายความถึงการถ่ายทอดทางพันธุกรรม ตามวิกิพีเดียMixinคือ:
ในภาษาโปรแกรมเชิงวัตถุมิกซ์อินคือคลาสที่มีเมธอดสำหรับใช้โดยคลาสอื่นโดยไม่จำเป็นต้องเป็นคลาสพาเรนต์ของคลาสอื่น ๆ คลาสอื่น ๆ เหล่านั้นเข้าถึงเมธอดของ mixin ได้อย่างไรนั้นขึ้นอยู่กับภาษา บางครั้งมีการอธิบายว่ามิกซ์อินเป็น "รวม" มากกว่า "สืบทอด"
โดยเฉพาะในภาษาเช่น perl สามารถเพิ่ม mixins ได้โดยใช้โมดูล Exporter:
package Mixins;
use Exporter qw(import);
our @EXPORT_OK = qw(pity);
# assumes it will be mixed-in to a class with a _who_do_i_pity method
sub pity {
my ($self) = @_;
printf("I pity %s\n", $self->_who_do_i_pity('da foo'));
}
ซึ่งสามารถผสมเข้ากับโมดูลใดก็ได้ที่มีวิธีการอย่างน้อยหนึ่งวิธีในแต่ละครั้ง:
package MrT
use Mixins qw(pity);
sub new {
return bless({}, shift);
}
sub _who_do_i_pity {
return 'da foo!'
}
จากนั้นในMrT
โมดูลของคุณสามารถใช้ได้ดังนี้:
use MrT;
MrT->new()->pity();
ฉันรู้ว่ามันเป็นตัวอย่างที่ไร้สาระ แต่มันได้ประเด็น ...
tl; dr
mixin และ multi inheritance มีรูปแบบเดียวกัน แต่มีความหมายที่แตกต่างกัน: mixin มีคลาสพื้นฐานให้การใช้งานฟังก์ชัน สำหรับการสืบทอดคลาสพื้นฐานจะจัดเตรียมอินเตอร์เฟสและคลาสย่อยมีการนำไปใช้
แต่อย่างไรก็ตามควรใช้องค์ประกอบมากกว่า mixin IMO
Mixins ถูกนำมาใช้อย่างมากมายในลักษณะที่คล้ายกัน
เหมือนกัน แต่ในบริบทที่แตกต่างกัน โดยปกติเมื่อเราพูดถึงการถ่ายทอดทางพันธุกรรมเรากำลังพูดถึงการถ่ายทอดทางพันธุกรรมแบบเดี่ยวและมิกซ์อินเป็นโครงสร้างที่อนุญาตให้มีการสืบทอดหลาย ๆ
นี่คือโครงสร้างภาษาที่มีการถกเถียงกันอย่างมากในโลก OOP เนื่องจาก:
แต่นอกเหนือจากนั้นเป็นโครงสร้างที่ทรงพลังซึ่งใช้ในภาษาและกรอบงานต่าง ๆ ตัวอย่างบางส่วน ได้แก่ :