מתודות Getter ו-Setter
חלק מהיחידה תכנות מונחה עצמים במסלול ה-GO של Coddy. שיעור 49 מתוך 107.
מכיוון שלא ניתן לגשת ישירות לשדות לא מיוצאים מחוץ לחבילה, צריך לספק מתודות שמאפשרות גישה מבוקרת. נהוג לקרוא להן פעולות גישה ופעולות הגדרה.
ב-Go, המוסכמה לגבי פונקציות גישה (getters) פשוטה: משתמשים בשם השדה עם אות ראשונה גדולה. לא מוסיפים את הקידומת "Get", אלא פשוט משתמשים ב-Balance(), ולא ב-GetBalance():
type BankAccount struct {
balance int // לא מיוצא
}
// Getter - מחזיר את הערך
func (b *BankAccount) Balance() int {
return b.balance
}
// Setter - משנה את הערך לאחר אימות
func (b *BankAccount) SetBalance(amount int) {
if amount >= 0 {
b.balance = amount
}
}
העוצמה האמיתית של פונקציות הגדרה היא בהוספת אימות או לוגיקה עסקית. במקום לאפשר לקוד חיצוני להגדיר כל ערך ישירות, אתה שולט במה שמותר:
func (b *BankAccount) Deposit(amount int) bool {
if amount <= 0 {
return false
}
b.balance += amount
return true
}
השיטה Deposit משמשת כפעולת הגדרה ייעודית האוכפת כללים: אין לאפשר הפקדות שליליות. קוד חיצוני חייב להשתמש בשיטות שלך, כדי להבטיח שהמבנה יישאר תמיד במצב תקין. זוהי הכמסה בפעולה: הסתרת הנתונים תוך חשיפת התנהגות מבוקרת.
אתגר
קלבואו נבנה ממיר טמפרטורות שמדגים כימוס תקין באמצעות שיטות getter ו-setter. תיצרו struct שמאחסן את הטמפרטורה באופן פנימי בצלזיוס, אך מספק גישה מבוקרת באמצעות שיטות עם אימות.
תארגנו את הקוד שלכם בשני קבצים:
temperature.go: צרו struct בשםTemperatureעם שדהcelsiusלא מיוצא (float64). ממשו את השיטות הבאות:Celsius()- getter שמחזירה את הטמפרטורה הנוכחית בצלזיוסSetCelsius(value float64)- setter שמקבלת רק ערכים השווים לאפס המוחלט או גבוהים ממנו (-273.15). אם הערך נמוך מסף זה, הטמפרטורה צריכה להישאר ללא שינוי.Fahrenheit()- מחזירה את הטמפרטורה לאחר המרתה לפרנהייט באמצעות הנוסחה:(celsius * 9/5) + 32SetFahrenheit(value float64)- ממירה את הקלט מפרנהייט לצלזיוס ושומרת אותו, אך רק אם ערך הצלזיוס שהתקבל שווה ל-273.15- או גבוה ממנו
NewTemperature(celsius float64) *Temperatureשיוצר טמפרטורה מאותחלת לערך הנתון (הניחו שהקלט לבנאי תקין).main.go: קראו ערכי טמפרטורה מהקלט והדגימו את שיטות ה-getter וה-setter. צרו טמפרטורה, הציגו את ערכיה בשתי היחידות, ואז נסו להגדיר ערכים חדשים והציגו את התוצאות.
הקלטים הבאים יסופקו:
- שורה 1: ערך התחלתי בצלזיוס
- שורה 2: ערך צלזיוס חדש להגדרה
- שורה 3: ערך פרנהייט חדש להגדרה
עצבו את כל פלטי הטמפרטורה עם שתי ספרות אחרי הנקודה העשרונית. הדפיסו את הרצף הבא:
- לאחר היצירה:
C: [celsius] F: [fahrenheit] - לאחר הגדרת צלזיוס:
C: [celsius] F: [fahrenheit] - לאחר הגדרת פרנהייט:
C: [celsius] F: [fahrenheit]
לדוגמה, עבור 25, -300 ו-212, הפלט שלכם צריך להיות:
C: 25.00 F: 77.00
C: 25.00 F: 77.00
C: 100.00 F: 212.00שימו לב שהערכים בשורה השנייה אינם משתנים, כי -300 נמוך מהאפס המוחלט, ולכן ה-setter דחתה אותו. השורה השלישית מציגה את הטמפרטורה לאחר הגדרה מוצלחת של 212°F (שמומר ל-100°C). זה הכוח של שיטות setter. הן אוכפות כללים ששומרים על תקינות הנתונים שלכם.
נסו בעצמכם
package main
import (
"fmt"
)
func main() {
// קרא את ערכי הקלט
var initialCelsius float64
var newCelsius float64
var newFahrenheit float64
fmt.Scanln(&initialCelsius)
fmt.Scanln(&newCelsius)
fmt.Scanln(&newFahrenheit)
// TODO: צור אובייקט Temperature חדש באמצעות הבנאי
// TODO: הדפס את הערכים ההתחלתיים בפורמט "C: [celsius] F: [fahrenheit]" עם 2 ספרות אחרי הנקודה העשרונית
// TODO: נסה להגדיר ערך Celsius חדש והדפס את התוצאה
// TODO: נסה להגדיר ערך Fahrenheit חדש והדפס את התוצאה
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות OOP ב-Go
קבצים חיצונייםסביבת העבודה והמודולים של Goחבילות וייבואשמות מיוצאים לעומת שמות לא מיוצאיםמבוא ל-OOP ב-GoStructs כמחלקותהגדרת מתודות עבור Structsמקבלי Pointer לעומת Valueאתחול Structפונקציות Constructorחזרה – מחשבון פשוט4ממשקים
מבוא לממשקיםמימוש משתמעממשק כחוזהממשק ריק (any)אימות טיפוסמתג טיפוסיםהרכבת ממשקיםממשקי Stringer ו-Errorסיכום – מחשבון צורות7כימוס
שדות מיוצאים לעומת שדות לא מיוצאיםכימוס ברמת החבילהמתודות Getter ו-Setterהסתרת מידע ב-Goסיכום – רשומות תלמידים10Generics (Go 1.18 ומעלה)
מבוא ל־Genericsפרמטרים של טיפוסיםאילוצי טיפוסיםמבנים גנרייםפתרון עוקף למתודות גנריותסיכום – אוסף גנרי2העמקה בסוגים וב-Structs
סוגים בסיסיים ומורכביםהגדרות של סוגים מותאמים אישיתתגיות StructStructs אנונימייםStructs מקונניםערכי אפס וברירות מחדלסיכום – ספר אנשי קשר5קומפוזיציה במקום ירושה
למה ב-Go אין ירושהיסודות הטמעת Structקידום מתודותהטמעת כמה Structsהטמעה לעומת אגרגציההסתרת מתודות מוטמעותסיכום – היררכיית עובדים8טיפול בשגיאות ו-OOP
ממשק errorסוגי שגיאות מותאמים אישיתעטיפת שגיאות (fmt.Errorf)שגיאות Sentinelerrors.Is() ו-errors.As()Panic, Defer ו-Recoverסיכום – מנתח קבצים11ספרייה סטנדרטית ותכנות מונחה עצמים
io.Reader ו-io.Writersort.Interfaceהממשק fmt.Stringerencoding/json עם מבניםהממשק http.Handlerסיכום – מודלים של REST API3מצביעים וזיכרון
יסודות המצביעים ב-Goמצביעים למבניםהעברה לפי ערך לעומת לפי הפניההפונקציה new()איסוף אשפה ב-Goסיכום - בונה רשימה מקושרת6פולימורפיזם ב-Go
פולימורפיזם באמצעות ממשקיםטיפוס ברווז ב-Goכללי התאמה לממשקאוספים פולימורפייםהזרקת תלויותסיכום - מעבד תשלומים9מקביליות ו-OOP
יסודות GoroutinesChannels ותקשורתChannel עם חוצץ לעומת ללא חוצץפקודת Selectsync.Mutex ו-sync.RWMutexsync.WaitGroupתכנון Struct בטוח לשימוש במקבילסיכום - מאגר עובדים12מושגים מתקדמים בתכנות מונחה עצמים
דפוס האפשרויות הפונקציונליותדפוס Builder ב-Goשרשור מתודותכינויי טיפוסים לעומת הגדרותיסודות Reflectionסקירה כללית של יצירת קודתרגלו בעצמכם: קומפיילר Go אונליין