خواص (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 است که به وسیله فاصله از هم جدا شدهاند.