מבוא לשפת סוויפט - swift
![](https://static.wixstatic.com/media/89f8ddf1ff65bd5086123b8856cf9d71.jpg/v1/fill/w_980,h_653,al_c,q_85,usm_0.66_1.00_0.01,enc_avif,quality_auto/89f8ddf1ff65bd5086123b8856cf9d71.jpg)
סוויפט שפה חדשה של אפל, המתפתחת ומשתנה כל הזמן בקצר מהיר (לקראת יציאת סוויפט 2),
כעת לאחר שהיא כבר יצאה בצורה רשמית ומחליפה את השפה הקודמת אובג'קטיב סי (objective c), אם כי חלק מהיכולות עדיין תלוי בשפה הקודמת ועובר התאמה לשפה החדשה.
נסקור בקצרה את התחביר שלה
כל משתנה חייב להתחיל בהצהרה var, או let במידה וזה משתנה קבוע - משתנה שערכו לא ניתן לשינוי (משפט אשר נשמע לא סותר את עצמו .. אבל הכוונה מובנת).
הטיפוסים הבסיסיים בשפה זו הם:
מספר שלם - Int
מספר ממשי (עד 6 ספרות אחרי הנקודה) - Float
מספר ממשי (64 ביט) - Double
בולאני - Bool
תו בודד (טבלת יוניקוד) - Character
מחרוזת - String
מערך - Array
מילון (מערך אסוציאטיבי) - Dictionary
על מנת לקבוע את הטיפוס של המשתנה, יש לציין זאת אחרי אופרטור נקודותיים.
לדוגמה:
var name:String
name="israel"
בקיצור ניתן לתת לו ערך ואז הוא אוטומטית מסווג את המשתנה כטיפוס מסויים.
לדוגמה:
var name="israel"
ואז אין אפשרות לשנות את ערכו לערך מספרי או בולאני,
כי הטיפוס שלו כבר נקבע להיות משתנה מסוג מחרוזת.
מחלקה מופשטת, הנקראת ממשק (interface) בשפות אחרות, בשפה זו נקראת פרוטוקול (Protocol).
זוהי מחלקה אשר אינה נותנת מימוש לשיטות (מתודות) שלה, אלא מציינת איזה שיטות ישנם.
אח"כ תגיע מחלקה אשר תירש ממנה ותממש אותם בהתאם לצרכים שלה.
יצירת מחלקה, כרגיל בשפות אחרות, נעשית על ידי המילה: class Car
על מנת ליצור ממה אובייקט, אין צורך במילה new, אלא נרשום:
var c = Car()
מבנה (Struct), בדיוק כמו מחלקה, ההבדל ביניהם שאובייקט של מבנה משכפל את עצמו בכל העתקה למשתנה אחר (value type), בדומה להעתקה מערך אשר כל שינוי במערך הראשון לא ישפיע על המערך השני שהוא מערך אחר לחלוטין שמחזיק כרגע אותם ערכים.
לעומת מחלקה אשר כל אובייקט המיוצר ממנה, במידה והוא מועתק למשתנה נוסף, מוחזק ההפנייה אל אותו אובייקט ראשוני (reference type), כי הוא בעצם מצביע על אותו אובייקט (כמו קיצור דרך לקובץ במחשב, שבלחיצה עליו נפתח אותו קובץ המקורי עליו יערכו כל השינויים שנבצע, בשונה מהעתקת קובץ).
על מנת להעביר משתנה ביי רפרנס (כי לפונקציה עובר רק הערך), נשתמש בסימן אמפרסנד בשליחה לפונקציה ומילה inout בתחילת הפונקציה:
y(&x);
func y(inout x:Int){
num=100;
}
במקרה הפוך, על מנת לוודע שהערך שאנחנו שמים במשתנה, יהיה רק לעותק היחיד הזה (לא ביי רפרנס), נרשום קודם פונקציה הבאה (אשר גורמת לו להיות עותק):
y.unshare
על מנת לאתחל מחלקה, נשתמש בבנאי הנקרא: init.
אפשר להעמיס אתחולים, זאת אומרת ליצור כמה סוגי אתחולים,
נגיד, אחד אשר לא מקבל ערך, שני שמקבל ערך מסוג אחד, שלישי המקבל ערך מטיפוס שונה, ורביעי שמקבל כמה ערכים. על פי הערכים שנעביר כפרמטרים בעת יצירת האובייקט, כך האובייקט יאותחל על ידי הבנאי המתאים.
על מנת לרשת ממחלקה אחרת נשתמש בסימון נקודתיים: class Car:Bus
על מנת לעשות הרחבה במחלקה בלי ליצור בן היורש ממנה, ניתן להשתמש בכלי מיוחד הנקרא הרחבה.
דוגמה:
extension Car{
func fast() { }
}
פונקציה נוצרת על ידי שימוש במילה fanc.
על מנת לומר שהפונציה מחזירה ערך, נשתמש בסימן חץ (<-).
דוגמה:
fanc fast() -> int { return 100 }
כל עוד אינה מחזיקה ערך אין צורך לציין זאת (בשונה משפות אחרות אשר מציינות שזה מחזיר void).
דוגמה לפונקציה שמקבלת כמות בלתי ידועה של פרמטרים מסוג כלשהו:
func car(nums:Int...)->Int{
var sum=0;
for n in nums{
sum+=n;
}
return sum;
}
var cars = car(1,2,3,4);
חשוב לדעת שבשפה זו (בשונה משפות אחרות כגון ג'אווה), הפרמטר של הפונקציה הוא קבוע (let) ואין אפשרות לשנותו בתוך הפונקציה, אלא אם קבענו שהוא משתנה רגיל על ידי המילה var.
דוגמה:
func car(var model:String){
model="I am" + model; // change value
println(model);
}
car("Volvo"); // prints I am Volvo
יש אופציה מיוחדת להקצות לפרמטר שם פנימי (לשימוש בפונקציה) ושם חיצוני (לשימוש בקריאה לפונקציה).
דוגמה בסיסית:
//defaults parameter
func car(model:String="Volvo"){
println("car \(model)");
}
car(model: "Honda"); //prints car Honda
car(); //prints car Volvo
דוגמה לשם חיצוני מותאם (על מנת שהקריאה לפונקציה תהיה ברורה יותר לנו):
func car(carModel model:String){
println(model);
}
car(carModel: "Volvo"); //prints Volvo
דוגמה לשם חיצוני ופנימי שהם אותו דבר, ניתן לקצר בשימוש סימן סולמית(#):
func car(#model:String){
println(model);
}
car(model:"Volvo"); //prints Volvo
תפל (tuple), הוא אובייקט המכיל מספר משתנים או ערכים, כמו מן מערך מיוחד, היכול להכיל סדרת ערכים מכמה טיפוסים שונים.
דוגמה:
var car = (100,"red");
println(car.0);
מערכים:
var cars:[Int]=[];
cars.append(90); // add
cars.removeLast(); // delete last
cars.count; // length of array
cars.insert(88, atIndex: 0); //asdd at
cars.removeAtIndex(2); //delete at
//inline declaration + initialization
var cars:[String]=["Mitsubishi ","Honda ","Mercedes","Peugeot","Porsche "];
// type(Int), size(3), values(1)
var threeOnes=[Int](count: 3, repeatedValue: 1);
מילונים:
var names:[String:Int]=["Israel":25,"David":31];
usersScores["Michael"]=45;
println(names);
// or iterate each keys & values
for (k,v) in names{
println(" \(k) has \(v)");
}
סוויפט היא שפה מהפכנית:
1. אם בשפות אחרות בתנאי, חייבים סוגרים עגולות והבלוק יכול להיות בלי סוגריים מסולסלות, כשזה שורה אחת.
כאן זה הפוך, התנאי לא חייב סוגריים והבלוק חייב סוגריים תמיד.
דוגמה:
if n1<n2{
println("n1 little");
}
2.
אם בתנאי מתג (swich) בשפות אחרות, אחרי כל מקרה (case) צריך לרשות עצור (break), כי אחרת הוא ימשיך לקרוא את ההמשך.
כאן זה הפוך, הוא לא ימשיך אל מעבר למקרה הרלוונטי, אלא אם כן נגדיר לו אחרת.
על ידי הפקודה: fallthrough
3.
בשפות אחרות ההנחה הבסיסית שישש בכל משתנה ערך מתאים וכל אובייקט קיים, אם מסתבר שהיה טעות, יש לתפוס את החריגות.
פה זה הפוך, אני לוקח את זה בעירבון מוגבל וכערך אופציונאלי, אלא אם במפורש אחרת על ידי סימן קריאה.
בשפה זו, הערכים נחשבים לאופציונאלים, מסומן בסימן שאלה (?), האומר שהם יכולים להיות לא מאותחלים (המחזיקים בערך nil הנקרא בשפות אחרות NULL), כל עוד לא כותבים במפורש לקומפיילר שזה ערך ודאי שאינו nil, על ידי סימן קריאה (!).
אגב, הערך nil או null, הוא אומר אפס (נול בגרמנית), אבל אין הכוונה לסיפרה אפס (טיפוס int) או לסטרינג ריק (טיפוס string), וכל אין הכוונה שהוא מחזיק ערך זבל כלשהו, אלא שהוא לא מחזיק ממש בכלום כלום...
כל פעם שאתם יוצרים מחלקה הוא (הקומפיילר) יחייב אותכם להשים ערך, או לפחות לגרום לו לקבל ערך על ידי הבנאי וכדומה. על מנת לוודא שזה יקבל ערך בזמן ריצה ולמנוע בעיות הנובעות ממשתנה או אובייקט שאינו מאותחל או אינו קיים.
דוגמא לערך אופציונאלי:
var name:String? // nil
דוגמה למשתנה שאנו יודעים בוודאות שלא יהיה ריק (במידה ויהיה ריק התוכנית תקרוס)
"var name:String! // String -> "israel
טיפים:
1. על מנת לבצע המרה (casting) לסטרינג בתוך מחרוזת, נשים את המשתנה בין סוגרים ומתחיל עם באק סלאש.
דוגמה:
println("the car ride \(fast) kilometer for hour");
2. לאפל יש כלי ששמו פליי גראונד באפליקצית Xcode (להורדה במערכת הפעלה מקינטוש),
כל עוד יש ותמיד יהיו באגים, אז לפעמים הקוד שכתבתם נכון ורק חסר רווחים, תוסיפו אותם ותראו שזה פשוט עובד! כמו כן, להוסיף סימן קריאה (או שאלה), גם יכול לעזור במקרה שזה מתאים.
3. ניתן שלא להשים נקודה-פסיק (;) בסוף שורה, ניתן לכתוב משתנים בשפות שאינם אנגלית, כמו עברית. וכן להשתמש במילה שמורה עם סימן אפוסטרוף (back pic), הנמצא ליד הטילדה (~) במקלדת.
לדוגמה: ... 3='var' או 3=ישראל.
אך זה לא תכנות בריא.
עוד נושא לסיום ושמו קלוסור (closure):
זהו למעשה טיפוס של מבנה של פונקציה או פונקציה אנונימית, אשר ניתן לקבוע אותה כערך למשתנה.
לדוגמה, משתנה n אשר מקבל פונקציה אנונימית המתאימה להגדרה שלו:
let n: Int -> Int; // declaration
n = {(x: Int)->Int in return x+x}; // initialization
למעשה n כעת הוא משתנה המחזיק פונקציה,
שבקריאתה היא תכפיל בשתיים ותחזיר את הערך המועבר אליה בפרמטר.
עוד נושא, ששמו מוטציה (Mutation),
וכן ישנם נושאים נוספים, כגון: lazy Stored Properties, Computed Properties, Subscripts, Enumeration
ועוד חזון למועד..