Menu
Coddy logo textTech

מתודות מופשטות

חלק מהיחידה תכנות מונחה עצמים במסלול ה-Dart של Coddy. שיעור 44 מתוך 110.

מתודה מופשטת היא מתודה שמוכרזת בתוך מחלקה מופשטת ואין לה גוף. היא מגדירה את חתימת המתודה, אך משאירה את המימוש לכל תת־מחלקה. כל מחלקה שיורשת את המחלקה המופשטת חייבת לדרוס את כל המתודות המופשטות, אחרת גם היא תהיה מופשטת.

abstract class Animal {
  // מתודה מופשטת - ללא גוף, תתי-המחלקות חייבות לממש אותה
  String makeSound();

  // מתודה קונקרטית - יש לה גוף, וכל תתי-המחלקות חולקות אותה
  void breathe() {
    print('Breathing...');
  }
}

class Dog extends Animal {
  @override
  String makeSound() {
    return 'Woof!';  // חובה לספק מימוש
  }
}

class Cat extends Animal {
  @override
  String makeSound() {
    return 'Meow!';  // מימוש שונה, אותה חתימה
  }
}

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

// אפשר להשתמש בטיפוס המופשט כטיפוס של משתנה
Animal a = Dog();
print(a.makeSound());  // הב הב!

Animal b = Cat();
print(b.makeSound());  // מיאו!

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

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

תכונהמתודה מופשטתמתודה קונקרטית
יש גוףלאכן
חובה לדרוסכןלא
מטרהלאכוף חוזהלשתף התנהגות
היכןבמחלקה מופשטת בלבדבכל מחלקה
challenge icon

אתגר

קל

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

תארגנו את הקוד שלכם בארבעה קבצים:

  • shape.dart: הגדירו מחלקה מופשטת Shape עם שדה final בשם color (String) ובנאי שמאתחל אותו. הכריזו על שתי שיטות מופשטות: double area() ו-double perimeter(). הוסיפו גם שיטה קונקרטית describe() שמדפיסה A [color] shape with area: [area] and perimeter: [perimeter]. מכיוון ש-area() ו-perimeter() הן שיטות מופשטות, כל תת-מחלקה תספק חישוב משלה, אבל describe() פועלת עבור כולן בלי צורך לדרוס אותה.
  • circle.dart: צרו מחלקה Circle שמרחיבה את Shape. יש לה שדה final בשם radius (double). הבנאי שלה מקבל את color ואת radius ומעביר את color אל super. ממשו את area() כך שתחזיר 3.14 * radius * radius, ואת perimeter() כך שתחזיר 2 * 3.14 * radius.
  • rectangle.dart: צרו מחלקה Rectangle שמרחיבה את Shape. יש לה שדות final בשם width ו-height (שניהם double). הבנאי שלה מקבל את color, את width ואת height, ומעביר את color אל super. ממשו את area() כך שתחזיר width * height, ואת perimeter() כך שתחזיר 2 * (width + height).
  • main.dart: ייבאו את כל הקבצים. צרו Circle עם הצבע 'red' ורדיוס 5.0, ו-Rectangle עם הצבע 'blue', רוחב 4.0 וגובה 6.0. קראו ל-describe() עבור כל צורה. לאחר מכן צרו List<Shape> שמכיל את שתי הצורות, עברו על הרשימה והדפיסו Area: [area] עבור כל צורה.

פלט צפוי:

A red shape with area: 78.5 and perimeter: 31.400000000000002
A blue shape with area: 24.0 and perimeter: 20.0
Area: 78.5
Area: 24.0

נסו בעצמכם

import 'shape.dart';
import 'circle.dart';
import 'rectangle.dart';

void main() {
  // TODO: צרו Circle עם צבע 'red' ורדיוס 5.0

  // TODO: צרו Rectangle עם צבע 'blue', רוחב 4.0 וגובה 6.0

  // TODO: קראו ל-describe() על המעגל

  // TODO: קראו ל-describe() על המלבן

  // TODO: צרו List<Shape> שמכילה את שתי הצורות

  // TODO: עברו על הרשימה והדפיסו "Area: [area]" עבור כל צורה
}
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר Dart אונליין