פרק 17: ירושה (Inheritance) ב-JavaScript

1. מה זה ירושה (Inheritance)?

ירושה היא אחד המאפיינים המרכזיים של תכנות מונחה עצמים (OOP). בעזרת ירושה ניתן ליצור מחלקה חדשה (Child Class) שמבוססת על מחלקה קיימת (Parent Class), וכך המחלקה החדשה יורשת את כל המאפיינים והשיטות של המחלקה המקורית. הירושה מאפשרת להרחיב או לשנות התנהגות של מחלקות קיימות מבלי לשנות את הקוד המקורי.

2. איך ירושה עובדת ב-JavaScript?

ב-JavaScript, ניתן להשתמש במילת המפתח extends כדי ליצור מחלקה חדשה שיורשת ממחלקה קיימת. המחלקה היורשת תוכל להוסיף מאפיינים ושיטות חדשים, או לשנות שיטות קיימות.

התחביר הבסיסי:

class ParentClass {
    // מאפיינים ושיטות של המחלקה הבסיסית
}

class ChildClass extends ParentClass {
    // מאפיינים ושיטות נוספים של המחלקה היורשת
}

3. דוגמה בסיסית לירושה

נניח שיש לנו מחלקה בסיסית שנקראת Person ואנחנו רוצים ליצור מחלקה חדשה בשם Student שתרחיב את היכולות של Person.

דוגמה:

// מחלקת הבסיס
class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }

    greet() {
        console.log("Hello, my name is " + this.name);
    }
}

// מחלקה יורשת
class Student extends Person {
    constructor(name, age, grade) {
        super(name, age); // קריאה ל-Constructor של המחלקה הבסיסית
        this.grade = grade;
    }

    study() {
        console.log(this.name + " is studying in grade " + this.grade);
    }
}

let student = new Student("Alice", 20, 10);
student.greet();  // מציג "Hello, my name is Alice"
student.study();  // מציג "Alice is studying in grade 10"

הסבר:

  • המחלקה Person היא מחלקת הבסיס ומכילה את המאפיינים name ו-age ושיטה בשם greet.
  • המחלקה Student יורשת ממחלקת Person באמצעות מילת המפתח extends.
  • בתוך ה-constructor של Student, אנחנו משתמשים ב-super כדי לקרוא ל-constructor של Person ולאתחל את המאפיינים name ו-age.
  • הוספנו מאפיין חדש בשם grade ושיטה חדשה בשם study.

4. שימוש ב-super

ב-JavaScript, המילה השמורה super מאפשרת לקרוא ל-constructor ולשיטות של המחלקה הבסיסית (המחלקה שממנה יורשים). זה עוזר לנו לאתחל את המאפיינים של המחלקה הבסיסית ולשמר התנהגות קיימת.

דוגמה עם super ב-Constructor:

class Animal {
    constructor(name) {
        this.name = name;
    }

    makeSound() {
        console.log(this.name + " makes a sound");
    }
}

class Dog extends Animal {
    constructor(name, breed) {
        super(name); // קריאה ל-Constructor של Animal
        this.breed = breed;
    }

    bark() {
        console.log(this.name + " barks! It's a " + this.breed);
    }
}

let dog = new Dog("Max", "Labrador");
dog.makeSound(); // מציג "Max makes a sound"
dog.bark();      // מציג "Max barks! It's a Labrador"

הסבר:

  • super משמשת לקריאה ל-constructor של המחלקה Animal, כדי לאתחל את המאפיין name.
  • המחלקה Dog מוסיפה מאפיין חדש (breed) ושיטה חדשה (bark).

5. ירושה של שיטות (Methods)

כאשר מחלקה יורשת ממחלקה אחרת, היא מקבלת את כל השיטות של המחלקה הבסיסית באופן אוטומטי. ניתן להוסיף שיטות חדשות במחלקה היורשת או להחליף שיטות קיימות על ידי דריסה (Override).

דוגמה להוספת שיטה חדשה:

class Employee {
    constructor(name, position) {
        this.name = name;
        this.position = position;
    }

    work() {
        console.log(this.name + " is working as a " + this.position);
    }
}

class Manager extends Employee {
    constructor(name, position, teamSize) {
        super(name, position);
        this.teamSize = teamSize;
    }

    manage() {
        console.log(this.name + " is managing a team of " + this.teamSize + " employees.");
    }
}

let manager = new Manager("Bob", "Team Lead", 5);
manager.work();  // מציג "Bob is working as a Team Lead"
manager.manage(); // מציג "Bob is managing a team of 5 employees."

הסבר:

  • המחלקה Manager יורשת את השיטה work מהמחלקה Employee.
  • בנוסף, המחלקה Manager מוסיפה שיטה חדשה בשם manage.

6. דריסת שיטות (Method Overriding)

כאשר מחלקה יורשת שיטה ממחלקה אחרת, ניתן לדרוס אותה על ידי הגדרת שיטה באותו שם במחלקה היורשת. בעזרת super, ניתן גם לקרוא לשיטה המקורית מתוך המחלקה הבסיסית.

דוגמה לדריסת שיטה:

class Animal {
    makeSound() {
        console.log("The animal makes a sound");
    }
}

class Dog extends Animal {
    makeSound() {
        super.makeSound(); // קריאה לשיטה המקורית במחלקת הבסיס
        console.log("The dog barks");
    }
}

let dog = new Dog();
dog.makeSound();
// מציג:
// "The animal makes a sound"
// "The dog barks"

הסבר:

  • המחלקה Dog דורסת את השיטה makeSound של Animal.
  • בעזרת super.makeSound(), אנחנו קוראים לשיטה המקורית של המחלקה Animal ולאחר מכן מוסיפים את ההתנהגות החדשה של הכלב ("The dog barks").

7. דוגמה מלאה: ירושה במערכת עובדים

נבנה מערכת ניהול עובדים שכוללת עובדים ומנהלים. המנהלים יירשו את ההתנהגות של העובדים אך יוסיפו גם התנהגות חדשה משלהם.

class Employee {
    constructor(name, position, salary) {
        this.name = name;
        this.position = position;
        this.salary = salary;
    }

    work() {
        console.log(this.name + " is working as a " + this.position);
    }

    getSalary() {
        console.log(this.name + " earns " + this.salary + " per year.");
    }
}

class Manager extends Employee {
    constructor(name, position, salary, teamSize) {
        super(name, position, salary);
        this.teamSize = teamSize;
    }

    manage() {
        console.log(this.name + " is managing a team of " + this.teamSize + " employees.");
    }

    getSalary() {
        super.getSalary(); // קריאה לשיטה המקורית במחלקה הבסיסית
        console.log(this.name + " also earns a bonus!");
    }
}

let employee = new Employee("John", "Developer", 50000);
employee.work();  // מציג "John is working as a Developer"
employee.getSalary(); // מציג "John earns 50000 per year."

let manager = new Manager("Alice", "Team Lead", 70000, 10);
manager.work();  // מציג "Alice is working as a Team Lead"
manager.manage(); // מציג "Alice is managing a team of 10 employees."
manager.getSalary(); // מציג "Alice earns 70000 per year." ולאחר מכן "Alice also earns a bonus!"

הסבר:

  • המחלקה Employee מכילה מאפיינים כמו שם, תפקיד, ושכר, וכן שיטות כמו work ו-getSalary.
  • המחלקה Manager יורשת את ההתנהגות של Employee, אבל מוסיפה את ההתנהגות הנוספת של ניהול צוות וגם דורסת את השיטה getSalary כדי להוסיף בונוס.
  • התוצאה היא שהמנהלים יכולים להשתמש בשיטות של Employee, אך עם התנהגות מורחבת.

סיכום

בפרק זה למדנו על:

  1. ירושה (Inheritance): יצירת מחלקות חדשות שמבוססות על מחלקות קיימות, באמצעות extends.
  2. השימוש ב-super: קריאה ל-constructor ולשיטות של המחלקה הבסיסית מתוך המחלקה היורשת.
  3. הוספת שיטות חדשות במחלקה היורשת ודריסת (Override) שיטות קיימות.
  4. שימוש ב-bind, call, ו-apply לשינוי ההקשר של פונקציות.

Scroll to Top
דילוג לתוכן