มีความแตกต่างหลากหลายรูปแบบสิ่งหนึ่งที่น่าสนใจคือความแตกต่างหลากหลายแบบพลวัต / พลวัตพลวัต
คำอธิบายระดับสูงมากของ polymorphism แบบรันไทม์คือการเรียกใช้เมธอดทำสิ่งต่าง ๆ โดยขึ้นอยู่กับชนิดของอาร์กิวเมนต์ของมัน: วัตถุนั้นมีหน้าที่ในการแก้ไขการเรียกเมธอด ทำให้มีความยืดหยุ่นสูง
หนึ่งในวิธีที่พบได้บ่อยที่สุดในการใช้ความยืดหยุ่นนี้สำหรับการฉีดแบบพึ่งพาเช่นฉันสามารถสลับระหว่างการใช้งานที่แตกต่างกันหรือการฉีดวัตถุจำลองเพื่อการทดสอบ หากฉันรู้ล่วงหน้าว่าจะมีตัวเลือกที่เป็นไปได้จำนวน จำกัด เท่านั้นฉันสามารถลอง hardcode ด้วยเงื่อนไขได้เช่น:
void foo() {
if (isTesting) {
... // do mock stuff
} else {
... // do normal stuff
}
}
ทำให้รหัสยากที่จะปฏิบัติตาม ทางเลือกคือการแนะนำอินเทอร์เฟซสำหรับการดำเนินการ foo และเขียนการใช้งานปกติและการใช้งานจำลองของอินเทอร์เฟซนั้นและ "ฉีด" เพื่อการใช้งานที่ต้องการที่รันไทม์ “ การฉีดพึ่งพา” เป็นคำที่ซับซ้อนสำหรับ“ ส่งวัตถุที่ถูกต้องเป็นอาร์กิวเมนต์”
เป็นตัวอย่างของโลกแห่งความจริงฉันกำลังทำงานกับปัญหาการเรียนรู้ของเครื่องจักร ฉันมีอัลกอริทึมที่ต้องใช้แบบจำลองการทำนาย แต่ฉันต้องการลองใช้อัลกอริทึมการเรียนรู้ของเครื่องที่แตกต่างกัน ดังนั้นฉันจึงกำหนดอินเทอร์เฟซ ฉันต้องการอะไรจากแบบจำลองการทำนายของฉัน รับตัวอย่างอินพุตการทำนายและข้อผิดพลาด:
interface Model {
def predict(sample) -> (prediction: float, std: float);
}
อัลกอริทึมของฉันรับฟังก์ชั่นจากโรงงานที่ใช้ฝึกโมเดล:
def my_algorithm(..., train_model: (observations) -> Model, ...) {
...
Model model = train_model(observations);
...
y, std = model.predict(x)
...
}
ตอนนี้ฉันมีการใช้งานอินเทอร์เฟซของโมเดลที่หลากหลายและสามารถเปรียบเทียบกับโมเดลอื่นได้ การใช้งานอย่างใดอย่างหนึ่งเหล่านี้ใช้เวลาจริงสองรุ่นอื่น ๆ และรวมเป็นแบบเพิ่ม ดังนั้นขอขอบคุณอินเทอร์เฟซนี้:
- อัลกอริทึมของฉันไม่จำเป็นต้องรู้เกี่ยวกับรุ่นเฉพาะล่วงหน้า
- ฉันสามารถสลับโมเดลได้อย่างง่ายดายและ
- ฉันมีความยืดหยุ่นอย่างมากในการนำโมเดลของฉันไปใช้
กรณีการใช้งานที่หลากหลายของ polymorphism อยู่ใน GUI ในกรอบ GUI เช่น Java AWT / Swing / ... มีที่แตกต่างกันส่วนประกอบ อินเทอร์เฟซคอมโพเนนต์ / คลาสพื้นฐานอธิบายการดำเนินการต่าง ๆ เช่นวาดภาพตัวเองไปยังหน้าจอหรือตอบสนองต่อการคลิกเมาส์ ส่วนประกอบจำนวนมากเป็นตู้คอนเทนเนอร์ที่จัดการส่วนประกอบย่อย คอนเทนเนอร์ดังกล่าวจะดึงตัวเองได้อย่างไร
void paint(Graphics g) {
super.paint(g);
for (Component child : this.subComponents)
child.paint(g);
}
ที่นี่ตู้คอนเทนเนอร์ไม่จำเป็นต้องรู้เกี่ยวกับประเภทย่อยที่แน่นอนของล่วงหน้า - ตราบใดที่พวกเขาสอดคล้องกับComponent
อินเตอร์เฟสคอนเทนเนอร์สามารถเรียกpaint()
เมธอดpolymorphic นี่ทำให้ฉันมีอิสระในการขยายลำดับชั้นของ AWT ด้วยองค์ประกอบใหม่โดยพลการ
มีปัญหาซ้ำ ๆ มากมายตลอดการพัฒนาซอฟต์แวร์ที่สามารถแก้ไขได้โดยการใช้ความหลากหลายเป็นเทคนิค ปัญหาที่เกิดซ้ำเหล่านี้ - คู่โซลูชันเรียกว่ารูปแบบการออกแบบและบางคู่ถูกรวบรวมในหนังสือที่มีชื่อเดียวกัน ในแง่ของหนังสือเล่มนั้นโมเดลการเรียนรู้ของเครื่องที่ถูกอัดฉีดของฉันจะเป็นกลยุทธ์ที่ฉันใช้เพื่อ“ กำหนดตระกูลอัลกอริธึม, แค็ปซูลแต่ละอันและทำให้พวกมันใช้แทนกันได้” ตัวอย่าง Java-AWT ที่เป็นส่วนประกอบที่สามารถมีองค์ประกอบย่อยคือตัวอย่างของหนึ่งคอมโพสิต
แต่ไม่ใช่ทุกการออกแบบที่จำเป็นต้องใช้ polymorphism (นอกเหนือจากการเปิดใช้งานการฉีดแบบพึ่งพาสำหรับการทดสอบหน่วยซึ่งเป็นกรณีการใช้งานที่ดีจริงๆ) ปัญหาส่วนใหญ่คงที่มาก เป็นผลให้คลาสและวิธีการมักจะไม่ใช้สำหรับ polymorphism แต่เพียงแค่เป็น namespaces ที่สะดวกสบายและสำหรับการเรียกวิธีการสวยไวยากรณ์ เช่นนักพัฒนาหลายคนชอบเรียกวิธีการเช่นผ่านการเรียกใช้ฟังก์ชันเทียบเท่าส่วนใหญ่account.getBalance()
Account_getBalance(account)
นั่นเป็นวิธีการที่ดีอย่างสมบูรณ์มันเป็นเพียงการเรียกว่า“ เมธอด” จำนวนมากไม่เกี่ยวข้องกับความหลากหลาย