אילו סוגי פולימורפיזם קיימים בשפת d?

שלום,
אשמח לדעת אילו סוגי פולימורפיזם קיימים בשפת D?
אשמח גם לראות דוגמה לכל אחד מהסוגים.
הדוקומנטציה של השפה לא ברורה (לינק).

היי גלעד, סוגי הפולימורפיזם הקיימים בשפת D הם:

העמסה (overloading) - נתינה של יותר ממשמעות אחת למושג. המשמעויות השונות יכולות, אולם אינן חייבות, להיות קשורות. נאמר שאופרטור מעומס אם האופרטור מייצג שתיים או יותר פונקציות שונות בעלות אותו שם. במילים אחרות, הגדרת פונקציה אחת או יותר עם שם זהה לפונקציה קיימת אך עם ארגומנטים שונים (כמות או סוג).
ניצור מחלקה (class) אשר נקראת printPerInput. מחלקה זו תכיל מספר פונקציות בעלות השם print, אשר פשוט מדפיסות את הארגומנט פר טיפוס. בכל פעם, נבצע קריאה לפונקציה ונעביר ערך מטיפוס מסוים.

import std.stdio;
import std.string;
class printPerInput {
    public:
        void print(int i) {
             writeln("Printing int: ",i);
        }
        void print(double d) {
             writeln("Printing double: ",d);
        }
        void print(string s) {
             writeln("Printing string: ",s);
        }
        void print(char c) {
             writeln("Printing char: ",c);
        }
        void print(bool b) {
             writeln("Printing bool: ",b);
        }
};

נציין כי ההעמסה היא מסוג context independent overloading שכן בחירת הפונקציה נקבעת בהתאמה לטיפוס שהפונקציה המועמסת מקבלת ללא תלות בערך החזרה.

המרה (coercion) - ישות אחת יכולה לשרת מספר טיפוסים הודות להמרה לא מפורשת (implicit), כלומר אוטומטית, של ערכים מטיפוס אחד לערכים מטיפוס אחר. בשפת D קיים מנגנון המרה מפורש (explicit coercion) בעזרת המילה cast. לדוגמה, בתוכנית הבאה, נוכל להמיר את המספר 97 לתו ע"פ הערך ה-ASCII שלו:

import std.stdio;
void main() {
   int x = 97;
   char y = cast (char) x;
   writeln("char: ",y);
}

פלט התוכנית הוא כמובן char: a.
כמו כן, בשפת D קיים מנגנון המרה מובלע (implicit coercion). לדוגמה, בתוכנית הבאה, נוכל להמיר משתנה מטיפוס double ולקבל ערך מטיפוס int:

import std.stdio;
void main() {
   double x;
   x = 3;
}

פולימורפיזם פרמטרי (parametric polymorphism) - פועל על הרבה טיפוסים שיש ביניהם קשר מסוים. הם בעצם מוגדרים בעזרת אופרטורים מסוימים על טיפוס גנרי כלשהו.
בדומה לשפת C++, גם שפת D משתמשים ב-templates כדי להשתמש בתכנות גנרי. לדוגמה, נוכל להגדיר template שמחזיר את החזקה של המספר:

import std.stdio;

template Square(T) {
    T Square(T t) {
        return t * t;
    }
}

void main() {
    writefln("The square of %s is %s", 3, Square!(int)(3));
    writefln("The square of %s is %s", 3.14, Square!(double)(3.14));
}

פלט התוכנית:

The square of 3 is 9
The square of 3.14 is 9.8596

פולימורפיזם הכלה (inclusion polymorphism) - ממומש על ידי רוב שפות תכנות מונחות-עצמים. מושג זה מתורת הטיפוסים אומר שמזהה עשוי להתייחס למופע השייך למספר כלשהו של מחלקות, כל עוד הן חולקות ביניהן מחלקת אם משותפת. פולימורפיזם כזה מנצל את היכולת לבצע חיפוש דינמי בזמן ריצה, ובביצוע דריסה של מתודות.
ניצור מחלקה אבסטרקטית (חלקה אשר מהווה בסיס למחלקות אחרות, אך אין לנו באמת צורך באובייקטים ממנה בתוכנית) בשם Vehicle. כמו כן, ניצור שני מחלקות Bus ו-Ship אשר יורשות מהמחלקה האבסטרקטית Vehicle. לכל אחת מהמחלקות הנ"ל קיימת פונקציה ציבורית move. כמו כן, ניצור פונקציה moveVehicle אשר קוראת לפונקציה move פר אובייקט.

import std.stdio;

abstract class Vehicle {
    void move() { }
};

class Bus: Vehicle {
    public:
        void move() {
            writeln("The bus moved");
        }
};

class Ship: Vehicle {
    public:
        void move() {
            writeln("The ship moved");
        }
};

void moveVehicle(Vehicle v) {
    v.move();
}

void main() {
    Bus b = new Bus();
    Ship s = new Ship();
    moveVehicle(b);
    moveVehicle(s);
}

פלט התוכנית:

The bus moved
The ship moved

בהצלחה.