خواص (Properties)

property (خصوصیت) استانداردی، برای دسترسی به فیلدهای با سطح دسترسی private در داخل یک کلاس می‌باشد. همانطور که در درس قبل اشاره شد، تعریف فیلدها در داخل کلاس به صورت public اشتباه است، چون کاربران می‌توانند با ایجاد یک شیء از کلاس به آنها دسترسی داشته باشند و هر مقداری که دوست دارند به آنها اختصاص دهند. برای رفع این مشکل مفهوم property ارائه شد. هر property دارای دو بخش می‌باشد، یک بخش جهت مقدار دهی (بلوک set) و یک بخش برای دسترسی به مقدار (بلوک get) یک داده private می‌باشد. در مثال زیر نحوه تعریف و استفاده از property آمده است :

 1: class Person
 2: {
 3:     private var name   : String
 4:     private var age    : Int
 5:     private var height : Double
 6: 
 7:     var Name: String         
 8:     {                        
 9:         get                  
10:         {                    
11:             return name      
12:         }                    
13:         set                  
14:         {                    
15:             name = newValue  
16:         }                    
17:     }                        
18: 
19:     var Age: Int                        
20:     {                        
21:         get                  
22:         {                    
23:             return age       
24:         }                    
25:         set                  
26:         {                    
27:             age = newValue   
28:         }                    
29:     }                        
30: 
31:     var Height: Double              
32:     {                        
33:         get                  
34:         {                    
35:             return height    
36:         }                    
37:         set                  
38:         {                    
39:             height = newValue
40:         }                              
41:     }                        
42: 
43:     init(_ name: String, _ age: Int, _ height: Double)
44:     {
45:         self.name   = name
46:         self.age    = age
47:         self.height = height
48:     }
49: }
50: 
51: var person1 = Person("Jack", 21, 160)
52: var person2 = Person("Mike", 23, 158)
53: 
54: print("Name  : \(person1.Name)")
55: print("Age   : \(person1.Age) years old")
56: print("Height: \(person1.Height) cm")
57: 
58: print() //Seperator                     
59: 
60: print("Name  : \(person2.Name)")
61: print("Age   : \(person2.Age) years old")
62: print("Height: \(person2.Height) cm")
63: 
64: person1.Name   = "Frank" 
65: person1.Age    = 19       
66: person1.Height = 162   
67: 
68: person2.Name   = "Ronald"
69: person2.Age    = 25       
70: person2.Height = 174   
71: 
72: print() //Seperator                     
73: 
74: print("Name  : \(person1.Name)")
75: print("Age   : \(person1.Age) years old")
76: print("Height: \(person1.Height) cm")
77: 
78: print()
79: 
80: print("Name  : \(person2.Name)")
81: print("Age   : \(person2.Age) years old")
82: print("Height: \(person2.Height) cm")
Name  : Jack
Age   : 21 years old
Height: 160.0 cm

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

Name  : Frank
Age   : 19 years old
Height: 162.0 cm

Name  : Ronald
Age   : 25 years old
Height: 174.0 cm

در برنامه بالا نحوه استفاده از property آمده است. همانطور که مشاهده می‌کنید در این برنامه ما سه فیلد (خطوط 5-3) تعریف کرده‌ایم (سه فیلد با سطح دسترسی private).

private var name   : String
private var age    : Int
private var height : Double

دسترسی به مقادیر این فیلدها فقط از طریق property های ارائه شده (خطوط 41-7) امکان پذیر است.

var Name: String
{                   
    get                  
    {                    
        return name     
    }                    
    set                  
    {                    
        name = newValue    
    }           
}

var Age: Int           
{                        
    get                  
    {                    
        return age      
    }                    
    set                  
    {                    
        age = newValue     
    }                    
}                        

var Height: Double        
{                        
    get                  
    {                    
        return height   
    }                    
    set                  
    {                    
        height = newValue  
    }                    
}                    

نام property ها همانند نام فیلدهای مربوطه می‌باشد با این تفاوت که حرف اول آنها بزرگ نوشته می‌شود. البته یادآور می‌شویم که شباهت نام property ها و فیلدها اجبار نیست و یک قرارداد می‌باشد.

به کلمه کلیدی newValue در داخل بلوک set توجه کنید. newValue همان مقداری است که از طریق property به فیلد اختصاص می‌دهیم. برای اختصاص یک مقدار به یک فیلد از طریق property کافیست که به صورت زیر عمل کنید :

Object.Property = Value

این کار (قرار دادن یک مقدار بعد از علامت مساوی) به منزله فراخوانی بخش set است. و ما به برنامه می‌فهمانیم که می‌خواهیم از طریق بخش set یک فیلد را مقداردهی کنیم. Object شیء ایجاد شده از کلاس، Property نام پراپرتی و Value مقداری است که می‌خواهیم به فیلد اختصاص دهیم. برای دسترسی به یک خاصیت می‌توانید از علامت دات (.) استفاده کنید. مثلاً برای اختصاص مقدار به سه فیلد age ،name و height از طریق property باید به صورت زیر عمل کنید :

person1.Name   = "Frank" 
person1.Age    = 19       
person1.Height = 162   

دستورات بالا بخش set مربوط به هر property را فراخوانی کرده و مقادیری به هر یک از فیلدها اختصاص می‌دهد. برای فراخوانی بخش get کافیست که نام شیء و سپس علامت نقطه و در آخر نام property را بنویسیم. با این کار به برنامه می‌فهمانیم که ما نیاز به مقدار فیلد داریم.

print("Name  : \(person1.Name)")
print("Age   : \(person1.Age) years old")
print("Height: \(person1.Height) cm")

به این نکته توجه کنید که در بخش get هم می‌توان تغییراتی بر روی فیلدها اعمال کرد. مثلاً فرض کنید که یک فیلد دارید که مقادیر پولی را در خود ذخیره می‌کند. شما می‌توانید در بخش get نحوه نمایش مقدار موجود در این فیلد را مشخص کنید. مثلاً خروجی به صورت سه رقم سه رقم نمایش داده شود. استفاده از property ها کد نویسی را انعطاف پذیر می‌کند مخصوصاً اگر بخواهید یک اعتبارسنجی برای اختصاص یک مقدار به فیلدها یا استخراج یک مقدار از آنها ایجاد کنید. پس می‌توان گفت که :

مثلاً شما می‌توانید یک محدودیت ایجاد کنید که فقط اعداد مثبت به فیلد age (سن) اختصاص داده شود. همانطور که در کد ابتدای درس مشاهده می‌کنید ما نوع فیلد age را Int قرار داده‌ایم. یعنی کاربر می‌تواند هر رقمی بین اعداد 2147483648- تا 2147483647 را به این فیلد اختصاص دهد. ولی چون غیر معقولانه است و سن (age) باید یک عدد مثبت و از لحاظ عقلی عددی از 1 تا 100 باشد می‌توانیم کاربر را با استفاده از بخش set مجبور کنیم که رقمی بین این دو عدد را به age اختصاص دهد. می‌توانید با تغییر بخش set خاصیت Age این کار را انجام دهید :

set                  
{                    
    if (newValue > 0 && newValue <= 100)
    {                                   
        age = newValue                  
    }			                
    else                                
    {			                
        age = 0                         
    }			                
}       

حال اگر کاربر بخواهد یک مقدار منفی به فیلد age اختصاص دهد مقدار age صفر خواهد شد. گاهی اوقات ممکن است که شما اصلاً نخواهید اعتبار سنجی انجام دهید. در این صورت بهتر است که آینده نگر باشید و باز هم به ازای هر فیلد موجود در کلاس یک خاصیت تعریف کنید. می‌توان یک property فقط خواندنی (read-only) ایجاد کرد. این property فاقد بخش set است. به عنوان مثال می‌توان یک خاصیت Name فقط خواندنی مانند زیر ایجاد کرد :

var Name: String
{                   
    get                  
    {                    
        return name     
    }                          
}

در این مورد اگر بخواهید یک مقدار جدید به فیلد name اختصاص دهید با خطا مواجه می‌شوید. نکته دیگری که باید به آن توجه کنید این است که شما می‌توانید برای بخش set سطح دسترسی ایجاد کنید. مثلا برای ایجاد سطح دسترسی private برای قسمت set مربوط به فیلد height کافیست که خط 5 کد ابتدای درس را به صورت زیر بنویسید:

private(set) var height : Double

خاصیت Name فقط در خارج از کلاس قابل خواندن است اما متدها فقط از طریق سازنده کلاس Person می‌توانند مقادیر جدید بگیرند. یک property می‌تواند دارای دو فیلد باشد. به کد زیر توجه کنید :

private var firstName : String
private var lastName  : String
   
var FullName: String
{                   
    get                  
    {                    
        return firstName + " " + lastName    
    }                           
}

همانطور که در مثال بالا مشاهده می‌کنید یک property فقط خواندنی تعریف کرده‌ایم که مقدار برگشتی آن ترکیبی از دو فیلد firstName و lastName است که به وسیله فاصله از هم جدا شده‌اند.