Menu
Coddy logo textTech

בטיחות מפני ערכי null במחלקות

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

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

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

class User {
  String name;           // חייב לעבור אתחול
  String? bio;           // אופציונלי - יכול להיות null
  int age = 0;           // יש לו ערך ברירת מחדל
  
  User(this.name);       // name מאותחל באמצעות פרמטר
}

בשדות שניתנים ל-null, אפשר להשאיר אותם ללא אתחול, מכיוון שברירת המחדל שלהם היא null. הדבר שימושי לנתונים אופציונליים:

class Product {
  String title;
  String? description;   // תיאור מוצר אופציונלי
  double? discount;      // ללא הנחה כברירת מחדל
  
  Product(this.title);
}

var item = Product('Laptop');
print(item.description);  // null
print(item.discount);     // null

בעת גישה לשדות שיכולים להיות null, השתמשו באופרטורים המודעים ל-null שלמדתם:

class Order {
  String id;
  User? customer;
  
  Order(this.id);
  
  String getCustomerName() {
    return customer?.name ?? 'Guest';
  }
}

מילת המפתח required בפרמטרים בעלי שם מבטיחה שהקוראים לפונקציה יספקו ערכים חיוניים:

class Account {
  String email;
  String? phone;
  
  Account({required this.email, this.phone});
}

var acc = Account(email: 'test@mail.com');  // phone הוא אופציונלי

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

challenge icon

אתגר

קל

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

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

  • reservation.dart: הגדירו מחלקה Reservation שמייצגת הזמנה למלון. כל הזמנה צריכה מידע חיוני מסוים, אבל פרטים מסוימים הם תוספות אופציונליות שהאורחים עשויים לספק או לא לספק. המחלקה שלכם צריכה לכלול:
    • String guestName שאינו nullable — לכל הזמנה חייב להיות שם אורח
    • int roomNumber שאינו nullable — לכל הזמנה חייב להיות מוקצה חדר
    • int nights שאינו nullable עם ערך ברירת מחדל 1 — השהייה המינימלית היא לילה אחד
    • String? specialRequests שהוא nullable — לאורחים עשויות להיות בקשות מיוחדות
    • DateTime? checkInTime שהוא nullable — ייתכן ששעת ההגעה המדויקת אינה ידועה
    • בנאי המשתמש בפרמטרים בעלי שם, עם required עבור guestName ו-roomNumber, בעוד ש-nights צריך להיות אופציונלי עם ערך ברירת המחדל שלו
    • מתודה getRequestsSummary() שמחזירה את הבקשות המיוחדות אם סופקו, או 'No special requests' באמצעות האופרטור ??
    • מתודה getArrivalInfo() שמחזירה את הייצוג כמחרוזת של שעת הצ'ק-אין באמצעות ?., או null אם לא הוגדרה
    • מתודה printConfirmation() שמציגה את פרטי ההזמנה
  • main.dart: ייבאו את מחלקת ההזמנה שלכם וצרו הזמנות שמציגות שילובים שונים של נתונים נדרשים ואופציונליים:
    • צרו הזמנה לאורחת 'Sarah Johnson' בחדר 101 למשך 3 לילות, עם בקשות מיוחדות 'Late checkout' ושעת צ'ק-אין שמוגדרת ל-DateTime(2024, 6, 15, 14, 30)
    • צרו הזמנה לאורח 'Mike Chen' בחדר 205 (השתמשו בברירת המחדל של מספר הלילות), והגדירו רק בקשות מיוחדות ל-'Extra pillows'
    • צרו הזמנה לאורחת 'Emma Davis' בחדר 310 למשך 2 לילות (השאירו את שני השדות האופציונליים כ-null)
    • עבור כל הזמנה לפי הסדר, קראו ל-printConfirmation(), ואז הדפיסו Arrival: [result] באמצעות getArrivalInfo()

המתודה printConfirmation() צריכה להדפיס בפורמט הזה:

=== Reservation Confirmed ===
Guest: [guestName]
Room: [roomNumber]
Nights: [nights]
Requests: [getRequestsSummary()]

הפלט הצפוי:

=== Reservation Confirmed ===
Guest: Sarah Johnson
Room: 101
Nights: 3
Requests: Late checkout
Arrival: 2024-06-15 14:30:00.000
=== Reservation Confirmed ===
Guest: Mike Chen
Room: 205
Nights: 1
Requests: Extra pillows
Arrival: null
=== Reservation Confirmed ===
Guest: Emma Davis
Room: 310
Nights: 2
Requests: No special requests
Arrival: null

נסו בעצמכם

import 'reservation.dart';

void main() {
  // TODO: צור הזמנה עבור 'Sarah Johnson'
  // חדר 101, 3 לילות, בקשות מיוחדות: 'Late checkout'
  // שעת הצ'ק-אין: DateTime(2024, 6, 15, 14, 30)
  
  // TODO: צור הזמנה עבור 'Mike Chen'
  // חדר 205, השתמש במספר הלילות המוגדר כברירת מחדל, בקשות מיוחדות: 'Extra pillows'
  // לא צוינה שעת צ'ק-אין
  
  // TODO: צור הזמנה עבור 'Emma Davis'
  // חדר 310, 2 לילות, ללא בקשות מיוחדות וללא שעת צ'ק-אין
  
  // TODO: עבור כל הזמנה לפי הסדר:
  // 1. קרא ל־printConfirmation()
  // 2. הדפס 'Arrival: [result]' באמצעות getArrivalInfo()
}
quiz iconבחנו את עצמכם

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

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

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