با عرض سلام و وقت بخیر خدمت کاربران سایت پی وی لرن . و کاربرانی که دوره کامل آموزش Swift را دنبال می کنند. کلاس ها ، ساختارها و شمارنده ها که در Swift 4 اعلام می شوند، برای ایجاد یک نمونه کلاس مقدار دهی اولیه می شوند، مقدار اولیه برای خصوصیات ذخیره شده و همچنین و برای نمونه های جدید نیز تعریف می شود. کلید واژه ی ایجاد تابع مقدار دهی اولیه ‘()init’ می باشد. initializer در Swift 4 با Objective-C در این مورد تفاوت دارد که مقدار را بازگشت نمی دهد. تابع initialization (مقدار دهی اولیه) برای بررسی مقادیر جدید و تازه ایجاد شده قبل از پردازش می باشد. برای آشنایی بیشتر با چگونگی کار با مقداردهی اولیه در Swift در ادامه ی این مبحث با ما همراه باشید.
در این آموزش شما با سینتکس و موارد مربوط به مقداردهی اولیه در Swift آشنا خواهید شد.
خصوصیات ذخیره شده باید نمونه هایی را برای کلاس ها و ساختارهای خود قبل از پردازش نمونه ها، آنالیز کنند.
خواص ذخیره شده از initializer برای اختصاص دادن و مقداردهی کردن مقادیر استفاده می کند.
بنابراین نیاز به فراخوانی خصوصیت observer نمی باشد.
Initializer در خصوصیات ذخیره شده استفاده می شود:
سینتکس :
1 2 3 | init() { //New Instance initialization goes here } |
مثال :
1 2 3 4 5 6 7 8 9 10 11 | struct rectangle { var length: Double var breadth: Double init() { length = 6 breadth = 12 } } var area = rectangle() print("area of rectangle is \(area.length*area.breadth)") |
نتیجه ی کامپایل و اجرای مثال فوق :
1 | area of rectangle is 72.0 |
در ساختار فوق ‘rectangle’ با اعضای length و breadth و با نوع داده ی ‘Double’ مقداردهی اولیه شده اند.
متد ()Init برای مقداردهی اعضای جدید و نوع double ایجاد شده است.
مساحت مستطیل با فراخوانی تابع rectangle محاسبه می شود.
زبان Swift 4 متد ()Init را برای مقداردهی اولیه خصوصیات ذخیره شده ارائه می دهد.
کاربر مقادیری را برای مقدار دهی اولیه در هنگام تعریف اعضای ساختار و کلاس هاست.
زمانیکه کاربر ارث بری کلاس ها و ساختارها را تعریف می کند، تنظیم مقادیر پیش فرض خصوصیات فعال می شود.
مثال :
1 2 3 4 5 6 7 | struct rectangle { var length = 6 var breadth = 12 } var area = rectangle() print("area of rectangle is \(area.length*area.breadth)") |
نتیجه ی کامپایل و اجرای مثال فوق :
1 | area of rectangle is 72 |
در زبان Swift 4 کاربر برای تعریف پارامترهای اولیه به عنوان بخشی از initializer از متد ()Init استفاده می کند.
مثال :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | struct Rectangle { var length: Double var breadth: Double var area: Double init(fromLength length: Double, fromBreadth breadth: Double) { self.length = length self.breadth = breadth area = length * breadth } init(fromLeng leng: Double, fromBread bread: Double) { self.length = leng self.breadth = bread area = leng * bread } } let ar = Rectangle(fromLength: 6, fromBreadth: 12) print("area is: \(ar.area)") let are = Rectangle(fromLeng: 36, fromBread: 12) print("area is: \(are.area)") |
نتیجه ی کامپایل و اجرای مثال فوق :
1 2 | area is: 72.0 area is: 432.0 |
پارامترهای اولیه هر دو نام پارامترهای محلی و عمومی را مشابه پارامترهای تابع و متد داراست.
اعلام پارامترهای محلی برای دسترسی به بدنه ی اولیه و اعلام پارامترهای خارجی نیز برای فراخوانی initializer استفاده می شود.
Swift 4 یک نام خارجی را برای هر یک از پارامترها در ()init اعلام می کند.
مثال :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | struct Days { let sunday, monday, tuesday: Int init(sunday: Int, monday: Int, tuesday: Int) { self.sunday = sunday self.monday = monday self.tuesday = tuesday } init(daysofaweek: Int) { sunday = daysofaweek monday = daysofaweek tuesday = daysofaweek } } let week = Days(sunday: 1, monday: 2, tuesday: 3) print("Days of a Week is: \(week.sunday)") print("Days of a Week is: \(week.monday)") print("Days of a Week is: \(week.tuesday)") let weekdays = Days(daysofaweek: 4) print("Days of a Week is: \(weekdays.sunday)") print("Days of a Week is: \(weekdays.monday)") print("Days of a Week is: \(weekdays.tuesday)") |
نتیجه ی کامپایل و اجرای مثال فوق :
1 2 3 4 5 6 | Days of a Week is: 1 Days of a Week is: 2 Days of a Week is: 3 Days of a Week is: 4 Days of a Week is: 4 Days of a Week is: 4 |
زمانیکه یک نام خارجی برای مقدار دهی اولیه نیاز ندارید، از کاراکتر ‘_’ برای اعمال رفتار پیش فرض استفاده می شود.
مثال :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | struct Rectangle { var length: Double init(frombreadth breadth: Double) { length = breadth * 10 } init(frombre bre: Double) { length = bre * 30 } init(_ area: Double) { length = area } } let rectarea = Rectangle(180.0) print("area is: \(rectarea.length)") let rearea = Rectangle(370.0) print("area is: \(rearea.length)") let recarea = Rectangle(110.0) print("area is: \(recarea.length)") |
نتیجه ی کامپایل و اجرای مثال فوق :
1 2 3 | area is: 180.0 area is: 370.0 area is: 110.0 |
هنگامی که خصوصیات ذخیره شده در برخی نمونه ها هیچ مقداری را برنمی گردانند، این خصوصیت از نوع ‘optional’ اعلام می شود.
دز این صورت مقدار ‘no value’ برای آن نوع خاص بازگردانده می شود.
زمانیکه خصوصبت ذخیره شده به عنوان ‘optional’ اعلام می شود، به طور خودکار مقدار “nil” در زمان مقدار دهی اولیه تنظیم می گردد.
مثال :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | struct Rectangle { var length: Double? init(frombreadth breadth: Double) { length = breadth * 10 } init(frombre bre: Double) { length = bre * 30 } init(_ area: Double) { length = area } } let rectarea = Rectangle(180.0) print("area is: \(rectarea.length)") let rearea = Rectangle(370.0) print("area is: \(rearea.length)") let recarea = Rectangle(110.0) print("area is: \(recarea.length)") |
نتیجه ی کامپایل و اجرای مثال فوق :
1 2 3 | area is: Optional(180.0) area is: Optional(370.0) area is: Optional(110.0) |
Initialization همچنین به کاربر اجازه می دهد تا مقدار خصوصیات ثابت را نیز دستکاری کند.
در طی initialization خصوصیت کلاس اجازه می دهد که کلاس های نمونه توسط ابرکلاس ها دستکاری شوند نه توسط زیر کلاس ها.
به عنوان مثال در برنامه قبلي ‘length’ به عنوان متغير در کلاس اصلي اعلام شده است.
در مثال زیر متغیر ‘length’ به عنوان یک ثابت اعلام شده است:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | struct Rectangle { let length: Double? init(frombreadth breadth: Double) { length = breadth * 10 } init(frombre bre: Double) { length = bre * 30 } init(_ area: Double) { length = area } } let rectarea = Rectangle(180.0) print("area is: \(rectarea.length)") let rearea = Rectangle(370.0) print("area is: \(rearea.length)") let recarea = Rectangle(110.0) print("area is: \(recarea.length)") |
نتیجه ی کامپایل و اجرای مثال فوق :
1 2 3 | area is: Optional(180.0) area is: Optional(370.0) area is: Optional(110.0) |
initializer های پیش فرض یک نمونه ی جدید را به تمام خصوصیات اعلام شده در کلاس پایه و ساختارها ارائه می دهند.
مثال:
1 2 3 4 5 6 7 8 9 10 | class defaultexample { var studname: String? var stmark = 98 var pass = true } var result = defaultexample() print("result is: \(result.studname)") print("result is: \(result.stmark)") print("result is: \(result.pass)") |
نتیجه ی کامپایل و اجرای مثال فوق :
1 2 3 | result is: nil result is: 98 result is: true |
برنامه ی فوق با نام کلاس ‘defaultexample’ تعریف شده است.
سه عضو تابع به نام های ‘studname?’ با ذخیره مقدار ‘nil’ ، متغیر ‘stmark’ با ذخیره مقدار ۹۸ و متغیر ‘pass’ از نوع Boolean با ذخیره مقدار ‘true’ مقداردهی اولیه شده اند.
به همین ترتیب، مقادیر عضو در کلاس می تواند به صورت پیش فرض قبل از پردازش انواع عضو کلاس، مقداردهی شود.
زمانیکه initializer سفارشی توسط کاربر معرفی نشده اند، انواع ساختار در Swift 4 به طور خودکار ‘memberwise initializer’ را دریافت می کنند.
این تابع اصلی برای مقدار دهی اولیه ی نمونه های ساختار جدید با memberwise initialize پیش فرض است.
سپس خصوصیات نمونه های جدید به memberwise initialize توسط نام ارسال می شوند.
مثال :
1 2 3 4 5 6 7 | struct Rectangle { var length = 100.0, breadth = 200.0 } let area = Rectangle(length: 24.0, breadth: 32.0) print("Area of rectangle is: \(area.length)") print("Area of rectangle is: \(area.breadth)") |
نتیجه ی کامپایل و اجرای مثال فوق :
1 2 | Area of rectangle is: 24.0 Area of rectangle is: 32.0 |
ساختارها در حالت پیش فرض برای توابع عضو خود در طول initialization با مقداردهی ‘length’ برابر با ‘۱۰۰٫۰’ و ‘breadth’ برابر با ‘۲۰۰٫۰’ تنظیم می شوند.
اما در طول پردازش برنامه متغیرهای length و breadth با مقادیر ۲۴٫۰ و ۳۲٫۰،در نظر گرفته می شوند.
Initializer Delegation برای فراخوانی initializer از سایر initializerها تعریف شده است.
کاربرد اصلی آن این است که به خاطر قابلیت استفاده ی مجدد، از تکرار کدها جلوگیری می کند.
مثال :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | struct Stmark { var mark1 = 0.0, mark2 = 0.0 } struct stdb { var m1 = 0.0, m2 = 0.0 } struct block { var average = stdb() var result = Stmark() init() {} init(average: stdb, result: Stmark) { self.average = average self.result = result } init(avg: stdb, result: Stmark) { let tot = avg.m1 - (result.mark1 / 2) let tot1 = avg.m2 - (result.mark2 / 2) self.init(average: stdb(m1: tot, m2: tot1), result: result) } } let set1 = block() print("student result is: \(set1.average.m1, set1.average.m2) \(set1.result.mark1, set1.result.mark2)") let set2 = block(average: stdb(m1: 2.0, m2: 2.0), result: Stmark(mark1: 5.0, mark2: 5.0)) print("student result is: \(set2.average.m1, set2.average.m2) \(set2.result.mark1, set2.result.mark2)") let set3 = block(avg: stdb(m1: 4.0, m2: 4.0), result: Stmark(mark1: 3.0, mark2: 3.0)) print("student result is: \(set3.average.m1, set3.average.m2) \(set3.result.mark1, set3.result.mark2)") |
نتیجه ی کامپایل و اجرای مثال فوق :
1 2 3 | (0.0,0.0) (0.0,0.0) (2.0,2.0) 5.0,5.0) (2.5,2.5) (3.0,3.0) |
Value Types | Class Types |
---|---|
وراثت برای انواع مقادیر مانند ساختارها و شمارنده ها پشتیبانی نمی شود. | وراثت پشتیبانی شده و تمام مقادیر ذخیره شده را بررسی می کند. |
انواع کلاس دو نوع initializer که با عنوان designated initializers و convenience initializers شناخته شده برای بررسی اینکه خصوصیات ذخیره شده مقدار اولیه را دریافت می کنند، دارند.
designated initializers و convenience initializers
Designated Initializer | Convenience Initializer |
---|---|
برای مقداردهی اولیه یک کلاس در نظر گرفته شده است. | در نظر گرفته شده به عنوان پشتیبانی اولیه برای یک کلاس. |
تمام خصوصیات کلاس مقداردهی اولیه شده اند و برای بازگشت بیشتر برای بازنشانی مناسب ابرکلاس نامیده می شوند. | Designated initializer به همراه convenience initializer برای ایجاد نمونه کلاس برای تشخیص نوع ورودی فراخوانی می شود. |
حداقل یک designated initializer برای هر کلاس تعریف شده است. | بدون نیاز به convenience initializers تعریف می شود زمانی که کلاس نیازی به اولیه سازی ندارد. |
{Init(parameters) { statements | {convenience init(parameters) { statements |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | class mainClass { var no1 : Int // local storage init(no1 : Int) { self.no1 = no1 // initialization } } class subClass : mainClass { var no2 : Int // new subclass storage init(no1 : Int, no2 : Int) { self.no2 = no2 // initialization super.init(no1:no1) } } let res = mainClass(no1: 10) let print = subClass(no1: 10, no2: 20) print("res is: \(res.no1)") print("res is: \(print.no1)") print("res is: \(print.no2)") |
نتیجه ی کامپایل و اجرای مثال فوق :
1 2 3 | res is: 10 res is: 10 res is: 20 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | class mainClass { var no1 : Int // local storage init(no1 : Int) { self.no1 = no1 // initialization } } class subClass : mainClass { var no2 : Int init(no1 : Int, no2 : Int) { self.no2 = no2 super.init(no1:no1) } override convenience init(no1: Int) { self.init(no1:no1, no2:0) } } let res = mainClass(no1: 20) let print = subClass(no1: 30, no2: 50) print("res is: \(res.no1)") print("res is: \(print.no1)") print("res is: \(print.no2)") |
نتیجه ی کامپایل و اجرای مثال فوق :
1 2 3 | res is: 20 res is: 30 res is: 50 |
Swift 4 اجازه نمی دهد که زیرکلاس ها در حالت پیش فرض initializer های ابر کلاس ها را برای انواع اعضای خود به ارث برند.
وراثت در initializer های ابر کلاس ها قابل اجراست.
زمانیکه کاربر نیاز دارد تا initializer ها در ابرکلاس ها تعریف شوند، زیر کلاس ها با initializer ها توسط کاربر برای پیاده سازی سفارشی تعریف شده است.
زمانیکه overriding توسط زیر کلاس در ابر کلاس تعریف شده باشد توسط کلید واژه ی ‘override’ تعریف شده است :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class sides { var corners = 4 var description: String { return "\(corners) sides" } } let rectangle = sides() print("Rectangle: \(rectangle.description)") class pentagon: sides { override init() { super.init() corners = 5 } } let bicycle = pentagon() print("Pentagon: \(bicycle.description)") |
نتیجه ی کامپایل و اجرای مثال فوق :
1 2 | Rectangle: 4 sides Pentagon: 5 sides |
مثال :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | class Planet { var name: String init(name: String) { self.name = name } convenience init() { self.init(name: "[No Planets]") } } let plName = Planet(name: "Mercury") print("Planet name is: \(plName.name)") let noplName = Planet() print("No Planets like that: \(noplName.name)") class planets: Planet { var count: Int init(name: String, count: Int) { self.count = count super.init(name: name) } override convenience init(name: String) { self.init(name: name, count: 1) } } |
نتیجه ی کامپایل و اجرای مثال فوق :
1 2 | Planet name is: Mercury No Planets like that: [No Planets] |
در هنگام تعریف یک کلاس، ساختار یا مقادیر شمارش شده، توسط کاربر، باید در صورت وقوع هر گونه خراب شدن اولیه، اطلاع رسانی شود.
مقداردهی اولیه متغیرها گاهی به علل زیر با خطا رو به رو می شود:
برای بذست آوردن catch exceptions توسط متدهای مقداردهی اولیه، Swift 4 یک مقدار اولیه انعطاف پذیر را به نام ‘initializer ناکام’ تولید می کند تا کاربر را مطلع کند.
کلید واژه ی ‘init?’ برای بدست آوردن مقداردهی اولیه ناموفق است، همچنین initializerهای ناموفق را نمی توان با یک نوع پارامتر و نام تعریف کرد.
مثال :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | struct studrecord { let stname: String init?(stname: String) { if stname.isEmpty {return nil } self.stname = stname } } let stmark = studrecord(stname: "Swing") if let name = stmark { print("Student name is specified") } let blankname = studrecord(stname: "") if blankname == nil { print("Student name is left blank") } |
نتیجه ی کامپایل و اجرای مثال فوق :
1 2 | Student name is specified Student name is left blank |
زبان Swift 4 انعطاف پذیری را برای initializer های غیر قابل اجرا برای شمارنده ها را نیز ارائه می کند.
مثال :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | enum functions { case a, b, c, d init?(funct: String) { switch funct { case "one": self = .a case "two": self = .b case "three": self = .c case "four": self = .d default: return nil } } } let result = functions(funct: "two") if result != nil { print("With In Block Two") } let badresult = functions(funct: "five") if badresult == nil { print("Block Does Not Exist") } |
نتیجه ی کامپایل و اجرای مثال فوق :
1 2 | With In Block Two Block Does Not Exist |
یک initializer غیر قابل اجرا زمانی که با شمارنده ها و ساختارها اعلام می شود، در مورد خطاهای اولیه در پیاده سازی اولیه آن هشدار می دهد.
با این حال، initializer نامعتبر در کلاسها، فقط بعد از خواندن خواص ذخیره شده به مقدار اولیه اخطار می دهد.
مثال :
1 2 3 4 5 6 7 8 9 10 11 | class studrecord { let studname: String! init?(studname: String) { self.studname = studname if studname.isEmpty { return nil } } } if let stname = studrecord(studname: "Failable Initializers") { print("Module is \(stname.studname)") } |
نتیجه ی کامپایل و اجرای مثال فوق :
1 | Module is Optional("Failable Initializers") |
همانند مقدار اولیه، کاربر همچنین دارای محدودیت هایی است که یک برنامه واسط برنامه نویسی ابر کلاس را در داخل زیر کلاس override می کند.
کلاس اولیه ابر کلاس نیز ممکن است با استفاده از یک واسط کاربری غیرقابل تصحیح زیر کلاس override شود.
یک مقداردهی اولیه ناکارآمد هرگز نمی تواند به یک مقداردهی مجدد ناموفق منتقل کند.
برنامه ای که در زیر آورده است، واسط های ناموفق و غیر قابل شکست را توصیف می کند.
مثال :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | class Planet { var name: String init(name: String) { self.name = name } convenience init() { self.init(name: "[No Planets]") } } let plName = Planet(name: "Mercury") print("Planet name is: \(plName.name)") let noplName = Planet() print("No Planets like that: \(noplName.name)") class planets: Planet { var count: Int init(name: String, count: Int) { self.count = count super.init(name: name) } override convenience init(name: String) { self.init(name: name, count: 1) } } |
نتیجه ی کامپایل و اجرای مثال فوق :
1 2 | Planet name is: Mercury No Planets like that: [No Planets] |
Swift 4 عبارت ‘init?’ را برای تعریف یک نمونه اولیه اختیاری ممکن است.
مثال :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | struct studrecord { let stname: String init!(stname: String) { if stname.isEmpty {return nil } self.stname = stname } } let stmark = studrecord(stname: "Swing") if let name = stmark { print("Student name is specified") } let blankname = studrecord(stname: "") if blankname == nil { print("Student name is left blank") } |
نتیجه ی کامپایل و اجرای مثال فوق :
1 2 | Student name is specified Student name is left blank |
برای اعلام هر زیرمجموعه از کلیدواژه ‘required’ اولیه باید قبل از تابع () init تعریف شود.
مثال :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | class classA { required init() { var a = 10 print(a) } } class classB: classA { required init() { var b = 30 print(b) } } let res = classA() let print = classB() |
نتیجه ی کامپایل و اجرای مثال فوق :
1 2 3 | 10 30 10 |
کلاس ها ، ساختارها و شمارنده ها که در Swift 4 اعلام می شوند، هر یک برای ایجاد یک نمونه از کلاس مقدار دهی اولیه می شوند، از این رو در این بخش شما را با مقداردهی اولیه در Swift و سیستم آن آشنا کردیم.