มรดก vs mixins ในภาษาแบบไดนามิก?


19

เมื่อใดที่คุณควรเลือกรูปแบบการสืบทอดมากกว่ามิกซ์อินเป็นภาษาไดนามิก

โดย mixins ฉันหมายถึงการผสมที่เหมาะสมตามจริงในขณะที่ใส่ฟังก์ชั่นและข้อมูลสมาชิกในวัตถุใน runtime

ตัวอย่างเช่นเมื่อใดที่คุณจะใช้การถ่ายทอดทางพันธุกรรมต้นแบบแทนที่จะเป็นมิกซ์อิน เพื่อแสดงให้เห็นชัดเจนยิ่งขึ้นว่าฉันหมายถึงอะไรโดยมิกซ์อินบางรหัสเทียม:

asCircle(obj) {
  obj.radius = 0
  obj.area = function() {
    return this.radius * this.radius * 3.14
  }

myObject = {}
asCircle(myObject)
myObject.area() // -> 0

2
มิกซ์อินเป็นเหมือนลักษณะตัดขวางมากกว่าการถ่ายทอดทางตรง ที่อาจจะกำหนดกรณีการใช้งานบางอย่างสำหรับคุณ
ashes999

1
องค์ประกอบทุกคน :)
OnesimusUnbound

คำตอบ:


14

การถ่ายทอดทางพันธุกรรมเป็นเรื่องง่าย มันมีข้อได้เปรียบเดียวมากกว่ามิกซ์อิน

นั่นคือมันเป็นลิงค์สด ถ้าคุณเปลี่ยนต้นแบบทุกอย่างที่สืบทอดมันเปลี่ยนไป

ตัวอย่างการใช้pd

var Circle = {
  constructor: function _constructor() {
    this.radius = 0;
    return this;
  },
  area: function _area() {
    return this.radius * this.radius * Circle.PI
  },
  PI: 3.14
};

var mixedIn = pd.extend({}, Circle).constructor();
var inherited = pd.make(Circle, {}).constructor();

Circle.perimeter = perimeter;

inherited.perimeter(); // wins
mixedIn.perimeter(); // fails

function perimeter() {
  return 2 * this.radius;
}

ดังนั้นโดยทั่วไปถ้าคุณต้องการเปลี่ยนแปลง "อินเตอร์เฟซ" วงกลมเพื่อสะท้อนเวลาทำงานกับวัตถุทั้งหมดที่ "ใช้" มันเป็นฟังก์ชั่นแล้วสืบทอดจากมัน

หากคุณไม่ต้องการให้มีการเปลี่ยนแปลงใด ๆ ให้ทำการผสมผสาน

โปรดทราบว่ามิกซ์อินมีจุดประสงค์มากกว่านั้นเช่นกัน Mixins เป็นกลไกของคุณสำหรับ "การสืบทอด" หลายรายการ

ถ้าคุณต้องการให้อ็อบเจกต์ใช้ "อินเตอร์เฟส" หลายอันคุณจะต้องผสมบางส่วนสิ่งที่คุณใช้สำหรับการสืบทอดต้นแบบเป็นสิ่งที่คุณต้องการให้การเปลี่ยนแปลงสะท้อนในขณะใช้งานส่วนอื่น ๆ จะผสมกัน


12

ความรู้สึกม้าของฉันบอกฉันนี้:

  • หากบางสิ่งมีประโยชน์ในหลาย ๆ วัตถุหรือลำดับชั้นของคลาส
  • หากสิ่งที่เป็นเพียงประโยชน์ตามลำดับชั้นเดียว - ใช้มรดก

หมายเหตุที่เกี่ยวข้อง:

  • คำว่า "มีประโยชน์" ควรถูกนำมาเปรียบเทียบ
  • สำหรับภาษาเหล่านั้นที่ไม่มีการสืบทอดหลายอย่างมิกซ์อินเป็นทางเลือกที่ดี
  • PHP 5.4 แนะนำลักษณะที่มีคุณงามความดีจากทั้งมิกซ์อินและโลกแห่งมรดก

+1 ตัวอย่างที่ชื่นชอบของ "สิ่งที่มีประโยชน์ในหลาย ๆ วัตถุหรือลำดับชั้นของคลาส" ใน Ruby คือโมดูลที่นับได้: ruby-doc.org/core-1.9.3/Enumerable.html
David

1
ฉันจะบอกว่าหลายมรดกอาจเป็นทางเลือก (ไม่ดี) เพื่อผสม
Simon Bergot

@Simon ฉันจะบอกว่า mixins สามารถเป็น (ไม่ดี) ทางเลือกให้กับมรดกหลาย;)
Raynos

ความรู้สึกม้าของฉันก็บอกฉันด้วย :)
theringostarrs

9

ใช้การทดสอบ "Is-a"

การรับมรดกจะถูก จำกัด ในกรณีที่คุณสามารถพูดว่า "Subclass IS A Superclass" พวกเขาเป็นสิ่งเดียวกัน "ชีสเป็นผลิตภัณฑ์นม"

Mixins สำหรับทุกสิ่งอื่น "ชีสสามารถใช้ในแซนวิช" ชีสไม่ใช่แซนด์วิช แต่มีส่วนร่วมในการทำแซนด์วิช

PS สิ่งนี้ไม่เกี่ยวกับภาษาแบบไดนามิก ภาษาการสืบทอดหลายภาษาที่มีการรวบรวมแบบสแตติก (เช่น C ++) มีจุดตัดสินใจเดียวกัน


+ 1- ภาษาคงที่แน่นอนมี mixins ด้วยเช่นกัน
DeadMG

ใช่มิกซ์อินสามารถทำได้หลายภาษา - นี่ไม่ใช่คำถามของฉัน ภาษาไดนามิกมีคุณสมบัติบางอย่างที่อาจหรือไม่ผสมมิกซ์และ / หรือน่าสนใจในภาษาดังกล่าว - Raynos ชี้ให้เห็นแง่มุมหนึ่ง นอกจากนี้คุณไม่ได้ชี้ให้เห็นถึงเหตุผลที่เฉพาะเจาะจงว่าทำไมจึงควรใช้แนวคิด IS A เหนือแนวคิด Mixin
Magnus Wolffelt

@ MagnusWolffelt: พวกเขาเป็นสิ่งเดียวกัน "ชีสเป็นผลิตภัณฑ์นม" นั่นคือกฎสำหรับ IS-A ฉันควรพูดอะไรอีก
S.Lott

คำถามของฉันเกี่ยวกับการตัดสินใจออกแบบมากขึ้นในสถานการณ์ใดที่คุณต้องการรับมรดกและด้วยเหตุผลอะไร ในภาษาแบบไดนามิกฉันเห็นเหตุผลสองสามข้อในการเลือกการถ่ายทอดทางพันธุกรรมเหนือมิกซ์อินนอกเหนือจากที่ Raynos อธิบายไว้ ประสิทธิภาพของการสร้างวัตถุอาจเป็นหนึ่งในเหตุผล
Magnus Wolffelt

@MagnusWolffelt: "ในสถานการณ์ที่คุณต้องการรับมรดก" เมื่อทั้งสองคลาสตอบสนองความสัมพันธ์ของ IS-A "ประสิทธิภาพของการสร้างวัตถุ" ไม่ใช่เหตุผลที่เลือกอย่างใดอย่างหนึ่ง การสืบทอดทำให้คำสั่งที่แข็งแกร่งมากเกี่ยวกับวัตถุสองคลาส Mixins ทำให้ข้อความที่อ่อนแอและยืดหยุ่นมากขึ้น การสืบทอดจะใช้เมื่อทั้งสองคลาสเป็นไปตามความสัมพันธ์ "IS-A" ฉันจะพูดอะไรอีก ฉันไม่เข้าใจคำถามของคุณเป็นอย่างดี คุณช่วยอธิบายให้ชัดเจนมากกว่าสิ่งที่คุณอยากรู้ได้ไหม?
S.Lott

0

ตัวอย่างที่ดีที่สุดที่ฉันสามารถมอบให้คุณได้คือนักแสดงสำหรับเกมที่มีการสืบทอดสำหรับบางสิ่งพื้นฐาน แต่ใช้มิกซ์ / ปลั๊กอินสำหรับการทำงานร่วมกัน ฟังก์ชั่นที่ใช้ร่วมกันอาจเป็น (โดยตรงจากซอร์สโค้ด!):

var plugins = {
    SingleVisualEntity : SingleVisualEntity,
    JumpBehaviour      : JumpBehaviour,
    WeaponBehaviour    : WeaponBehaviour,
    RadarBehaviour     : RadarBehaviour,
    EnergyGatherer     : EnergyGatherer,
    LifeBarPlugin      : LifeBarPlugin,
    SelectionPlugin    : SelectionPlugin,
    UpgradePlugin      : UpgradePlugin,
    BrainPlugin        : BrainPlugin,
    PlanetObjectPlugin : PlanetObjectPlugin,
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.