سازنده (initializer)

سازنده‌ها، متدهای خاصی هستند که وجود آنها برای ساخت اشیاء لازم است. آن‌ها به شما اجازه می‌دهند که مقادیری را به هر یک از فیلدهای کلاس اختصاص دهید و کدهایی که را که می‌خواهید هنگام ایجاد یک شیء اجرا شوند را به برنامه اضافه کنید. اگر از هیچ سازنده‌ای در کلاستان استفاده نکنید، کامپایلر، از سازنده پیشفرض، که یک سازنده بدون پارامتر است، استفاده می‌کند. می‌توانید در برنامه‌تان از تعداد زیادی سازنده استفاده کنید که، دارای پارامترهای متفاوتی باشند. در مثال زیر یک کلاس که شامل سازنده است را، مشاهده می‌کنید:

 1: class Person
 2: {
 3:     var name  : String
 4:     var age   : Int
 5:     var height: Double
 6: 
 7:     init()                  			      
 8:     {                           			      
 9:         name   = "No Name"
10:         age    = 0        
11:         height = 0.0      
12:     }                            			      
13: 
14:     init(n: String, a: Int, h: Double)
15:     {				      
16:         self.name   = n 	      
17:         self.age    = a 	        
18:         self.height = h 	        
19:     }				      
20: 
21:     func ShowInformation()
22:     {
23:         print("Name  : \(name)")
24:         print("Age   : \(age) years old")
25:         print("Height: \(height) cm")
26:     }
27: }
28: 
29: var firstPerson  = Person()               
30: var secondPerson = Person(n: "Mike", a: 23, h: 158)
31:                                                   
32: firstPerson.name   = "Jack"                        
33: firstPerson.age    = 21                            
34: firstPerson.height = 160                        
35: firstPerson.ShowInformation()                   
36:                                                   
37: print() //Separator
38:                                                   
39: secondPerson.ShowInformation()
Name: Jack
Age: 21 years old
Height: 160cm

Name: Mike
Age: 23 years old
Height: 158cm

همانطور که مشاهده می‌کنید، در مثال بالا، دو سازنده را به کلاس Person اضافه کرده‌ایم. یکی از آنها سازنده پیشفرض (خطوط 12-7) و دیگری سازنده‌ای است که سه آرگومان قبول می‌کند (خطوط 19- 14). در داخل بدنه سازنده پیشفرض (خطوط 11-9)، مقادیر پیشفرضی به فیلدهای کلاس (خطوط 5-3) اختصاص داده‌ایم. سازنده‌ها نیز مانند توابع می‌توانند سربارگذاری شوند. حال اجازه دهید که چطور می‌توانیم یک سازنده خاص را هنگام تعریف یک نمونه از کلاس فراخوانی کنیم:

var firstPerson  = Person()               
var secondPerson = Person(n: "Mike", a: 23, h: 158)

در اولین نمونه ایجاد شده از کلاس Person از سازنده پیشفرض استفاده کرده‌ایم چون پارامتری برای دریافت آرگومان ندارد. در دومین نمونه ایجاد شده، از سازنده‌ای استفاده می‌کنیم، که دارای سه پارامتر است. اگر خطوط 34-32 را حذف، برنامه را کامپایل و اجرا کنید، مقادیر پیشفرضی که در خطوط 11-9 به فیلدها اختصاص داده‌ایم در خروجی نمایش داده می‌شوند.
اگر بخواهید بجز این مقادیر پیشفرض، مقادیر دیگری به فیلدها اختصاص دهید، کافیست که یک شیء از کلاس ایجاد کرده و سپس فیلدها را مقداردهی کنید (کاری که در خطوط 34-32 انجام داده‌ایم). حال به شیء دوم که از سازنده دارای پارامتر استفاده می‌کند، توجه کنید، مشاهده می‌کنید که با فراخوانی تابع ShowInformation() همه چیز همانطور که انتظار می‌رود اجرا می‌شود. این بدین دلیل است که شما هنگام تعریف نمونه و از قبل مقادیری به هر یک از فیلدها اختصاص داده‌اید، بنابراین، آن‌ها نیاز به مقدار دهی مجدد ندارند، مگر اینکه، شما بخواهید این مقادیر را اصلاح کنید.

استفاده از کلمه کلیدی self

راهی دیگر برای ایجاد مقادیر پیشفرض استفاده از کلمه کلیدی self است. مثال زیر اصلاح شده مثال قبل است و نحوه استفاده از 4 سازنده با تعداد پارامترهای مختلف را نشان می‌دهد:

 1: class Person                                        
 2: {   
 3:     var  name  : String                                
 4:     var  age   : Int                                   
 5:     var  height: Double                                
 6:                                                            
 7:     init()                                                      
 8:     {
 9:         name   = "No Name"
10:         age    = 0
11:         height = 0                                              
12:     } 
13: 
14:     convenience init(name: String) 
15:     {
16:         self.init(name: name, age: 0, height: 0)
17:     } 
18: 
19:     convenience init(name: String, age: Int) 
20:     {
21:         self.init(name: name, age: age, height: 0)
22:     } 
23: 
24:     init(name: String, age: Int, height: Double) 
25:     {
26:         self.name   = name
27:         self.age    = age
28:         self.height = height
29:     }                                                           
30:                                                                 
31:     func ShowInformation()                          
32:     {                                                      
33:         print("Name  : \(name)")              
34:         print("Age   : \(age) years old")     
35:         print("Height: \(height) cm\n")      
36:     }                                                      
37: }                                                          
38:                                                                 
39: var firstPerson  = Person()                 
40: var secondPerson = Person(name: "Jack")          
41: var thirdPerson  = Person(name: "Mike",  age: 23)      
42: var fourthPerson = Person(name: "Chris", age: 18, height: 152)
43:                                                     
44: firstPerson.ShowInformation()                     
45: secondPerson.ShowInformation()                    
46: thirdPerson.ShowInformation()                    
47: fourthPerson.ShowInformation()                                  
Name  : No Name
Age   : 0 years old
Height: 0.0 cm

Name  : Jack
Age   : 0 years old
Height: 0.0 cm

Name  : Mike
Age   : 23 years old
Height: 0.0 cm

Name  : Chris
Age   : 18 years old
Height: 152.0 cm

ما چهار سازنده بری اصلاح کلاسمان تعریف کرده‌ایم. شما می‌توانید تعداد زیادی سازنده برای مواقع لزوم در کلاس داشته باشید. اولین سازنده یک سازنده پیشفرض است (سازنده اصلی). دومین سازنده یک پارامتر از نوع رشته دریافت می‌کند (خطوط 17-14). سومین سازنده دو پارامتر (خطوط 22-19) و چهارمین سازنده سه پارامتر می‌گیرد (خطوط 29-24). به چهارمین سازنده توجه کنید. سه سازنده دیگر به این سازنده وابسته هستند. در خطوط 12-7 یک سازنده پیشفرض بدون پارامتر تعریف شده است. توجه کنید که از کلمه کلیدی convenience باید قبل از کلمه کلیدی ()init استفاده کنید. با آنکه Swift از سربارگذاری توابع و سازنده‌ها پشتیبانی می‌کند ولی استفاده از کلمه کلیدی convenience به شما اجازه می‌دهد که از تکرار کدنویسی جلوگیری کنید. توجه کنید که تمام سازنده‌هایی که با convenience شروع می‌شوند باید سازنده اصلی را فراخوانی کنند. این کار با استفاده از کلمه کلیدی self انجام می‌شود (خطوط 16 و 21).

حال به نحوه فراخوانی این سازنده‌ها می‌پردازیم. در خطوط 42-39 ما سه چهار شیء از کلاس Person ایجاد کرده‌ایم. در خط 39 هیچ پارامتری به سازنده کلاس Person نداده‌ایم در نتیجه سازنده پیشفرض (خطوط 12-7) فراخوانی شده و مقادیر 0.0، 0، No Name چاپ می‌شوند. در خط 40 ما یک آرگومان رشته‌ای به سازنده ارسال کرده‌ایم. کامپایلر به طور خودکار سازنده‌ای که دارای یک پارامتر است (خطوط 17-14) را فراخوانی می‌کند. در این سازنده ما یک پارامتر تعریف کرده‌ایم ولی در خط 16 آن، مقادیر پیشفرضی به فیلدهای age و height داده‌ایم. وقتی این پارامتر با یک مقدار رشته‌ای پر شد، سپس به پارامترهای سازنده چهارم ارسال شده و در کنار دو مقدار پیشفرض دیگر (0 برای age و 0.0 برای height) قرار می‌گیرد. این روند در مورد بقیه سازنده‌ها نیز صدق می‌کند. در داخل بنده هر کدام از سازنده‌ها، اگر کدی نوشته شود، در ابتدای همه کدها اجرا می‌شوند.

همانطور که مشاهده می‌کنید با ایجاد چندین سازنده برای یک کلاس، چندین راه برای ایجاد یک شیء بر اساس داده‌هایی که نیاز داریم به وجود می‌آید. در مثال بالا 4 نمونه از کلاس Person ایجاد کرده‌ایم و چهار تغییر در سازنده آن به وجود آورده‌ایم. سپس مقادیر مربوط به فیلدهای هر نمونه را نمایش می‌دهیم. یکی از موارد استفاده از کلمه کلیدی self به صورت زیر است. فرض کنید نام پارامترهای متد کلاس شما یا سازنده، شبیه نام یکی از فیلدها باشد:

init(name: String, age: Int, height: Double)
{				      
    name   = name 	      
    age    = age 	      
    height = height 	      
}

این نوع کدنویسی ابهام بر انگیز است و کامپایلر نمی‌تواند متغیر را تشخیص داده و مقداری به آن اختصاص دهد. اینجاست که از کلمه کلیدی self استفاده می‌کنیم:

init(name: String, age: Int, height: Double)
{				      
    self.name   = name 	      
    self.age    = age 	      
    self.height = height 	      
}

قبل از هر فیلدی کلمه کلیدی self را می‌نویسیم و نشان می‌دهیم که این همان چیزی است که می‌خواهیم به آن مقداری اختصاص دهیم.