Menu
Coddy logo textTech

גטרים וסטרים

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

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

class Temperature {
    double celsius;    // פרטי - אי אפשר לגשת אליו ישירות
    
public:
    // פונקציית קריאה - מחזירה את הערך
    double getCelsius() const {
        return celsius;
    }
    
    // פונקציית עדכון - משנה את הערך לאחר בדיקת תקינות
    void setCelsius(double value) {
        if (value >= -273.15) {    // בדיקה מול האפס המוחלט
            celsius = value;
        }
    }
};

הכוח האמיתי של פונקציות הגדרה הוא אימות.

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

גם getters יכולים לעבד נתונים לפני שהם מחזירים אותם:

class Temperature {
    double celsius;
public:
    double getCelsius() const { return celsius; }
    
    // getter מחושב - אינו מאחסן fahrenheit, אלא מחשב אותו
    double getFahrenheit() const {
        return celsius * 9.0 / 5.0 + 32.0;
    }
    
    void setCelsius(double value) { celsius = value; }
};

שימו לב למילת המפתח const ב-getters — היא מציינת שהם אינם משנים את האובייקט. Setters אינם יכולים להיות const, מכיוון שמטרתם היא לשנות ערכי איברים. דפוס זה של שימוש ב-getters וב-setters הוא יסודי לכימוס, ומעניק לכם שליטה מלאה על אופן הגישה לנתוני המחלקה שלכם ועל אופן השינוי שלהם.

challenge icon

אתגר

קל

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

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

  • Player.h: הגדירו מחלקת Player שמנהלת את הפרופיל של דמות במשחק באמצעות גישה מוגנת לנתונים. המחלקה שלכם צריכה לכלול:
    • חברים פרטיים: name (מחרוזת), level (int) ו-experience (int)
    • בנאי שמקבל שם ומאתחל את level ל-1 ואת experience ל-0
    • getter בשם getName() שמחזירה את שם השחקן
    • getter בשם getLevel() שמחזירה את הרמה הנוכחית
    • getter בשם getExperience() שמחזירה את נקודות הניסיון הנוכחיות
    • setter בשם setName() שמקבלת רק שמות באורך של לפחות 3 תווים; אם השם אינו תקין, השאירו את השם הנוכחי ללא שינוי
    • setter בשם addExperience(int points) שמקבלת רק ערכים חיוביים. כשנקודות הניסיון מגיעות ל-100 או עולות עליו, השחקן עולה רמה: הגדילו את הרמה ב-1 והפחיתו 100 מנקודות הניסיון. הדבר יכול להתרחש כמה פעמים אם מתווספות מספיק נקודות ניסיון.
    • getter מחושבת בשם getExperienceToNextLevel() שמחזירה כמה נקודות ניסיון נוספות דרושות כדי להגיע לרמה הבאה (תמיד 100 - current experience)

    סמנו את כל ה-getters בתור const, מכיוון שהם לא משנים את האובייקט.

  • main.cpp: הדגימו את פעולת ה-getters וה-setters שלכם. קראו מהקלט שם שחקן ונקודות ניסיון להוספה (כל אחד בשורה נפרדת), ואז:
    • צרו Player עם השם שהתקבל בקלט
    • הדפיסו "Player: <name>, Level: <level>, XP: <experience>"
    • הוסיפו את נקודות הניסיון שהתקבלו בקלט באמצעות addExperience()
    • הדפיסו שוב את אותה שורת מצב כדי להציג את המצב המעודכן
    • הדפיסו "XP to next level: <amount>"
    • נסו לשנות את השם ל-"Al" (האימות אמור להיכשל)
    • הדפיסו "Name after invalid change: <name>"
    • שנו את השם ל-"Champion" (השינוי אמור להצליח)
    • הדפיסו "Name after valid change: <name>"

קלט נקודות הניסיון יסופק כמחרוזת שתצטרכו להמיר למספר שלם. כללו את קובץ הכותרת שלכם ב-main.cpp באמצעות #include "Player.h".

נסו בעצמכם

#include <iostream>
#include <string>
#include "Player.h"

using namespace std;

int main() {
    // קרא את שם השחקן
    string playerName;
    getline(cin, playerName);

    // קרא את נקודות הניסיון שיש להוסיף (כמחרוזת, המר ל-int)
    string expString;
    getline(cin, expString);
    int expToAdd = stoi(expString);

    // TODO: צור Player עם השם שהוזן

    // TODO: הדפס את המצב ההתחלתי: "Player: <name>, Level: <level>, XP: <experience>"

    // TODO: הוסף את נקודות הניסיון שהוזנו באמצעות addExperience()

    // TODO: הדפס את שורת המצב המעודכנת

    // TODO: הדפס "XP to next level: <amount>"

    // TODO: נסה לשנות את השם ל-"Al" (האימות אמור להיכשל)

    // TODO: הדפס "Name after invalid change: <name>"

    // TODO: שנה את השם ל-"Champion" (השינוי אמור להצליח)

    // TODO: הדפס "Name after valid change: <name>"

    return 0;
}
quiz iconבחנו את עצמכם

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

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

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