ממשק ריק (any)
חלק מהיחידה תכנות מונחה עצמים במסלול ה-GO של Coddy. שיעור 28 מתוך 107.
ממשק ריק הוא ממשק שאין בו מתודות. מכיוון שלכל טיפוס ב-Go יש לפחות אפס מתודות, כל טיפוס מקיים אוטומטית את הממשק הריק. לכן הוא יכול להכיל ערכים מכל טיפוס.
var anything interface{}
anything = 42
anything = "hello"
anything = true
anything = []int{1, 2, 3}החל מ-Go 1.18, מילת המפתח any הוצגה ככינוי ל-interface{}. הם ניתנים להחלפה לחלוטין, אבל קל יותר לקרוא את any.
var value any = "Go is awesome"הממשק הריק שימושי כשצריך לטפל בערכים מסוג לא ידוע או משתנה. פונקציות כמו fmt.Println משתמשות בו כדי לקבל ארגומנטים מכל סוג:
func PrintAnything(v any) {
fmt.Println("Value:", v)
}
func main() {
PrintAnything(100)
PrintAnything("text")
PrintAnything(3.14)
}עם זאת, יש לכך מחיר. כאשר ערך נשמר בממשק ריק, מאבדים את הגישה למידע הספציפי על הטיפוס שלו.
אי אפשר לקרוא ישירות למתודות או לגשת לשדות בלי לחלץ תחילה את הטיפוס הבסיסי. בשיעורים הבאים נלמד כיצד לשלוף את הטיפוס הממשי מתוך ממשק ריק באמצעות הצהרות טיפוס ומתגי טיפוס.
אתגר
קלבואו נבנה מיכל אחסון גמיש שיכול להכיל ערכים מכל סוג באמצעות הממשק הריק. תיצרו קופסה פשוטה שמדגימה כיצד any מאפשר לאחסן סוגים שונים באותו מבנה.
תארגנו את הקוד שלכם בשני קבצים:
box.go: הגדירו מבנהBoxעם שדה יחידContentמסוגany. צרו פונקציית בנאיNewBoxשמקבלת ערך מכל סוג ומחזירה מצביע ל-Box שמכיל את הערך הזה. הוסיפו מתודהDescribeשמחזירה מחרוזת המציגה מה מאוחסן בקופסה.main.go: קראו ערכים שונים מהקלט, צרו קופסאות שמכילות מספר שלם, מחרוזת וערך בוליאני, ואז הדפיסו את התיאור של כל קופסה כדי להראות כיצד אותו סוג Box יכול להכיל ערכים שונים לחלוטין.
הקלטים הבאים יסופקו:
- שורה 1: ערך של מספר שלם
- שורה 2: ערך מחרוזת
- שורה 3: ערך בוליאני (
trueאוfalse)
המתודה Describe שלכם צריכה להחזיר מחרוזת בפורמט הבא:
Box contains: [value]לדוגמה, עבור 42, hello ו-true, הפלט שלכם צריך להיות:
Box contains: 42
Box contains: hello
Box contains: trueהתובנה המרכזית כאן היא שמבנה Box יחיד יכול לאחסן מספר שלם, מחרוזת או ערך בוליאני: כל זאת משום שהטיפוס any מקבל ערכים מכל סוג. כל קופסה מכילה משהו אחר, ובכל זאת כולן מאותו סוג Box.
נסו בעצמכם
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// קרא ערך שלם
line1, _ := reader.ReadString('\n')
intVal, _ := strconv.Atoi(strings.TrimSpace(line1))
// קרא ערך מחרוזת
line2, _ := reader.ReadString('\n')
strVal := strings.TrimSpace(line2)
// קרא ערך בוליאני
line3, _ := reader.ReadString('\n')
boolVal, _ := strconv.ParseBool(strings.TrimSpace(line3))
// TODO: צור תיבות לכל ערך באמצעות NewBox
// TODO: הדפס את התיאור של כל תיבה באמצעות המתודה Describe
// השתמש במשתנים כדי למנוע שגיאות קומפילציה (הסר שורות אלה בעת המימוש)
_ = intVal
_ = strVal
_ = boolVal
// דוגמה לפורמט הפלט:
// fmt.Println(box.Describe())
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
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 אונליין