מחלקות ב-TypeScript

מחלקות ב-TypeScript

מאמר זה מסביר על מחלקות ב-TypeScript.

YouTube Video

מחלקות ב-TypeScript

מחלקות ב-TypeScript מבוססות על מחלקות ES6 של JavaScript ומציעות תכונות נוספות כמו אנוטציות סוגים ומחוללי גישה. זה מאפשר להשתמש במושגים מתכנות מונחה עצמים תוך הבטחת בטיחות סוגים חזקה וברורה יותר.

להלן הסברים על השימוש הבסיסי והתכונות של מחלקות ב-TypeScript.

הגדרת מחלקה בסיסית

 1class Person {
 2    name: string;  // Member variable
 3    age: number;   // Member variable
 4
 5    // Constructor
 6    constructor(name: string, age: number) {
 7        this.name = name;
 8        this.age = age;
 9    }
10
11    // Method
12    greet(): void {
13        console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
14    }
15}
16
17const person = new Person("Alice", 25);
18person.greet();  // Hello, my name is Alice and I am 25 years old.
  • המשתנים name ו-age הם מאפיינים (משתני מחלקה) של המחלקה.
  • ה-constructor הוא מתודה שנקראת בעת יצירת מופע של מחלקה, אשר מקבלת פרמטרים ומקצה ערכים למאפיינים.
  • greet היא מתודה של המחלקה, המציינת שאין לה ערך מוחזר על ידי היותה מסוג void.

מחוללי גישה

ב-TypeScript, ניתן להשתמש במחוללי גישה (public, private, protected) לשליטה בגישה למאפייני ומתודות המחלקה.

public

בברירת מחדל, כל המאפיינים והמתודות הם public. משמעות הדבר היא שניתן לגשת אליהם מחוץ למחלקה.

 1class Animal {
 2    public species: string;
 3
 4    constructor(species: string) {
 5        this.species = species;
 6    }
 7
 8    public makeSound(): void {
 9        console.log(`${this.species} makes a sound.`);
10    }
11}
12
13const animal = new Animal("Dog");
14console.log(animal.species);  // Dog
15animal.makeSound();           // Dog makes a sound.
  • המאפיין species והשיטה makeSound מוגדרים כ-public וניתן לגשת אליהם מחוץ למחלקה.

private

שימוש במחולל private מונע גישה למאפיינים או למתודות מחוץ למחלקה.

 1class Car {
 2    private brand: string;
 3
 4    constructor(brand: string) {
 5        this.brand = brand;
 6    }
 7
 8    public getBrand(): string {
 9        return this.brand;
10    }
11}
12
13const car = new Car("Toyota");
14// console.log(car.brand);  // Error: 'brand' is private and cannot be accessed.
15console.log(car.getBrand());  // Toyota
  • המאפיין brand מוגדר כ-private, ולכן אי אפשר לגשת אליו מחוץ למחלקה.
  • אפשר להשיג אינקפסולציה של נתונים על ידי הסתרת מאפיינים בעזרת המגדיר private.

protected

מחולל protected מגביל גישה מחוץ למחלקה אך מאפשר גישה בתתי-מחלקה (מחלקות נגזרות).

 1class Vehicle {
 2    protected model: string;
 3
 4    constructor(model: string) {
 5        this.model = model;
 6    }
 7}
 8
 9class Truck extends Vehicle {
10    public getModel(): string {
11        return this.model;
12    }
13}
14
15const truck = new Truck("Ford F-150");
16console.log(truck.getModel());  // Ford F-150
17
18// console.log(truck.model);
19// Error: Property 'model' is protected and only accessible within class 'Vehicle' and its subclasses.
  • המאפיין model מוגדר כ-protected, ולכן לא ניתן לגשת אליו מחוץ למחלקה, אבל אפשר לגשת אליו מתוך מחלקות יורשות.

משיגים ומקצים

ב-TypeScript, ניתן להגדיר משיגים ומקצים באמצעות מילות המפתח get ו-set כדי לקבל ולהגדיר ערכי מאפיינים.

 1class Employee {
 2    private _salary: number;
 3
 4    constructor(salary: number) {
 5        this._salary = salary;
 6    }
 7
 8    // Getter
 9    get salary(): number {
10        return this._salary;
11    }
12
13    // Setter
14    set salary(newSalary: number) {
15        if (newSalary > 0) {
16            this._salary = newSalary;
17        } else {
18            console.log("Salary must be positive.");
19        }
20    }
21}
22
23const employee = new Employee(50000);
24console.log(employee.salary);  // 50000
25employee.salary = 60000;
26console.log(employee.salary);  // 60000
27employee.salary = -100;        // Salary must be positive.
  • בדוגמה זו, נעשה שימוש ב-getter ו-setter עבור המאפיין salary כדי לשלוט בגישה ועדכונים חיצוניים. ה-setter מבצע בדיקת תוקף כדי למנוע ערכים שליליים, ומציג הודעת אזהרה אם ניתן ערך לא תקין.

ירושה

ב-TypeScript, ניתן לרשת מחלקות. באמצעות מילת המפתח extends, ניתן לרשת יכולות ממחלקת אב.

 1class Animal {
 2    constructor(public name: string) {}
 3
 4    public move(): void {
 5        console.log(`${this.name} is moving.`);
 6    }
 7}
 8
 9class Bird extends Animal {
10    public fly(): void {
11        console.log(`${this.name} is flying.`);
12    }
13}
14
15const bird = new Bird("Sparrow");
16bird.move();  // Sparrow is moving.
17bird.fly();   // Sparrow is flying.
  • בדוגמה זו, מחלקת Bird יורשת ממחלקת Animal, מה שמאפשר לה להשתמש בשיטה move של Animal. בנוסף, היא מגדירה שיטה משלה fly, וכך מוסיפה פונקציונליות חדשה תוך ירושת תכונות ממחלקת האב.

מחלקות אבסטרקטיות

מחלקות אבסטרקטיות (abstract) אינן ניתנות ליצירת מופע ישיר ומשמשות כתבניות לספק מימושים קונקרטיים בתתי-מחלקות.

 1abstract class Shape {
 2    abstract getArea(): number;
 3
 4    public describe(): void {
 5        console.log("This is a shape.");
 6    }
 7}
 8
 9class Circle extends Shape {
10    constructor(private radius: number) {
11        super();
12    }
13
14    public getArea(): number {
15        return Math.PI * this.radius * this.radius;
16    }
17}
18
19const circle = new Circle(5);
20console.log(circle.getArea());  // 78.53981633974483
21circle.describe();  // This is a shape.
  • בדוגמה זו, Shape מוגדרת כמחלקה אבסטרקטית, ו-getArea היא שיטה אבסטרקטית שחייבת להיות ממומשת על ידי מחלקות יורשות. מחלקת Circle יורשת את המחלקה האבסטרקטית הזו ומממשת את השיטה getArea שלה לחישוב שטח של עיגול. בנוסף, שיטות ממשיות כמו describe נרשות כפונקציונליות משותפת וניתן להשתמש בהן כפי שהן.

קשר עם ממשקים

מחלקות יכולות לממש ממשקים, כדי לוודא שיש להן מאפיינים ומתודות ספציפיים.

 1interface Flyable {
 2    fly(): void;
 3}
 4
 5class Airplane implements Flyable {
 6    public fly(): void {
 7        console.log("The airplane is flying.");
 8    }
 9}
10
11const airplane: Flyable = new Airplane();
12airplane.fly();  // The airplane is flying.
  • בדוגמה זו, הממשק Flyable מגדיר את המפרט עבור השיטה fly, ומחלקת Airplane מממשת את הממשק הזה על ידי מתן מימוש מוחשי לשיטה fly. באמצעות זה, מובטח שלכל אובייקט שניתן לטפל בו כטיפוס Flyable תהיה שיטת fly.

חברים סטטיים

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

 1class MathUtils {
 2    static PI: number = 3.14;
 3
 4    static add(a: number, b: number): number {
 5        return a + b;
 6    }
 7}
 8
 9console.log(MathUtils.add(10, 20)); // 30
10console.log(MathUtils.PI); // 3.14
  • מגדירים שיטות סטטיות באמצעות מילת המפתח static.
  • בדוגמה זו, מחלקת MathUtils מגדירה שיטה סטטית בשם add ומאפיין סטטי בשם PI.
  • חברים סטטיים אינם שייכים למופעי המחלקה, אלא ניתן לקרוא להם ישירות מהמחלקה עצמה.

סיכום

מחלקות ב-TypeScript מוסיפות מאפיינים כמו בטיחות סוג, מגני גישה ומחלקות מופשטות לפונקציונליות של מחלקות JavaScript. זה מאפשר תכנות מונחה עצמים חזק ובטוח יותר.

תוכלו לעקוב אחר המאמר שלמעלה באמצעות Visual Studio Code בערוץ היוטיוב שלנו. נא לבדוק גם את ערוץ היוטיוב.

YouTube Video