خواص (Properties)
همانطور که قبلا گفته شد، متغیرهای نمونه در Ruby به صورت پیشفرض دارای سطح دسترسی Private بوده و در خارج از کلاس قابل دسترسی نیستند. در درس های قبلی اشاره شد که برای دسترسی به متغیرهای نمونه باید از متد استفاده شود. یک قرارداد در Ruby برای دسترسی به متغیرهای نمونه وجود دارد و آن استفاده از Setter و Getter می باشد. Setter و Getter که به آنها Property هم گفته می شود در واقع دو متد هستند که از آنها برای مقداردهی و دسترسی به مقدار متغیرهای نمونه استفاده می شود. در مثال زیر نحوه تعریف و استفاده از property آمده است :
1: class Person 2: 3: def setName=(name) 4: @name = name 5: end 6: 7: def getName 8: @name 9: end 10: 11: def setAge=(age) 12: @age = age 13: end 14: 15: def getAge 16: @age 17: end 18: 19: def setHeight=(height) 20: @height = height 21: end 22: 23: def getHeight 24: @height 25: end 26: 27: end 28: 29: person1 = Person.new 30: person1.setName = "Frank" 31: person1.setAge = 19 32: person1.setHeight = 162 33: puts "name : #{person1.getName}" 34: puts "age : #{person1.getAge} years old" 35: puts "height: #{person1.getHeight}cm" 36: 37: puts #Seperator 38: 39: person2 = Person.new 40: person2.setName = "Ronald" 41: person2.setAge = 25 42: person2.setHeight = 174 43: puts "name : #{person2.getName}" 44: puts "age : #{person2.getAge} years old" 45: puts "height: #{person2.getHeight}cm"
name : Frank age : 20 years old height: 162cm name : Ronald age : 25 years old height: 174cm
در برنامه بالا نحوه استفاده از property آمده است. همانطور که مشاهده میکنید در این برنامه ما سه خاصیت (خطوط 25-3) تعریف کردهایم. این خصایت ها که هر کدام دارای دو متد هستند، کار مقداردهی و گرفتن مقدار سه متغیر نمونه age ،@name@ و height@ را انجام می دهند. در داخل کلاس متدهایی میبینید، که نام برخی از آنها با کلمه set و برخی دیگر با کلمه get شروع شده اند.
به این نکته توجه کنید که به طور قرار دادی، در نامگذاری متدهای set و get ابتدا این دو کلمه و سپس نام متغیرهای نمونه با حرف بزرگ میآیند. مثلاً در همین مثال بالا برای متغیر نمونه name متدها به صورت setName و getName نامگذاری میشوند. نکته دیگری که در خطوط 3، 11 و 19 وجود دارد این است که بعد از نام متدهایی که با کلمه set شروع می شوند، علامت مساوی قرار داده می شود و در دو طرف این علامت مساوی نباید هیچ فاصله ای گذاشته شود. برای دسترسی به یک خاصیت میتوانید از علامت . استفاده کنید.
person1.setName = "Frank"
دستور بالا بخش set مربوط به property را فراخوانی کرده و مقداری به متغیر نمونه اختصاص میدهد. برای فراخوانی متدهای getter کافیست که نام شیء و سپس علامت نقطه و در آخر نام property را بنویسیم. با این کار به برنامه میفهمانیم که ما نیاز به مقدار متغیرهای نمونه داریم:
puts "name : #{person1.getName}" puts "age : #{person1.getAge} years old" puts "height: #{person1.getHeight}cm"
به این نکته توجه کنید که در متدهای getter میتوان تغییراتی بر روی متغیرها اعمال کرد. مثلاً فرض کنید که یک متغیر دارید که مقادیر پولی را در خود ذخیره میکند. شما میتوانید در متد getter نحوه نمایش مقدار موجود در این متغیر را مشخص کنید. مثلاً خروجی به صورت سه رقم سه رقم نمایش داده شود. استفاده از property ها کد نویسی را انعطاف پذیر میکند مخصوصاً اگر بخواهید یک اعتبارسنجی برای اختصاص یک مقدار به متغیرها یا استخراج یک مقدار از آنها ایجاد کنید. پس میتوان گفت که :
مثلاً شما میتوانید یک محدودیت ایجاد کنید که فقط اعداد مثبت بین 0 تا 100 به متغیر age (سن) اختصاص داده شود. همانطور که در کد ابتدای درس مشاهده میکنید ما متغیر age را برای سن شخص در نظر گرفته ایم. ولی کاربر میتواند هر رقمی به این فیلد اختصاص دهد ولی چون غیر معقولانه است و سن (age) باید یک عدد مثبت و از لحاظ عقلی عددی از 1 تا 100 باشد میتوانیم کاربر را با استفاده از متد setter مربوط به این متغیر مجبور کنیم که رقمی بین این دو عدد را به age اختصاص دهد. خطوط 13-11 کد ابتدای درس را با کدهای زیر جایگزین کرده و مقادیر منفی و یا بالاتر از 100 را به فیلد age اختصاص داده و نتیجه را مشاهده کنید :
def setAge=(age) if age > 0 and age <= 100 @age = age else @age = 0 end end
مشاهده می کنید اگر کاربر بخواهد یک مقدار منفی و یا بزرگتر از صفر به متغیر age اختصاص دهد مقدار age صفر خواهد شد.
attr_reader ،attr_writer و attr_accessor
اینکه به ازای هر متغیر نمونه، دو متد جهت مقداردهی و دریافت مقدار آنها تعریف کنیم، خسته کننده بوده و کد ما را شلوغ می کند. برای رفع این مشکل در نسخه های جدید Ruby سه متد attr_writer ،attr_reader و attr_accessor اضافه شده اند که کار را خیلی راحت می کنند. حال می خواهیم کد ابتدای درس را با استفاده از این متدها بنویسیم:
1: class Person 2: 3: attr_writer :name, :age, :height 4: attr_reader :name, :age, :height 5: 6: end 7: 8: person1 = Person.new 9: person1.name = "Frank" 10: person1.age = 20 11: person1.height = 162 12: puts "name : #{person1.name}" 13: puts "age : #{person1.age} years old" 14: puts "height: #{person1.height}cm" 15: 16: puts #Seperator 17: 18: person2 = Person.new 19: person2.name = "Ronald" 20: person2.age = 25 21: person2.height = 174 22: puts "name : #{person2.name}" 23: puts "age : #{person2.age} years old" 24: puts "height: #{person2.height}cm"
name : Frank age : 20 years old height: 162cm name : Ronald age : 25 years old height: 174cm
خطوط 3 و 4 کد بالا، کار خطوط 25-3 کد ابتدای درس را می کنند. متد attr_writer در حکم متدهایی که با set شروع می شوند و متد attr_reader در حکم متدهایی که با get شروع می شوند، می باشد. یعنی متد attr_writer کار مقداردهی و متد attr_reader کار گرفتن مقدار متغیرهای نمونه را بر عهده دارد. به طور خلاصه خطوط 3 و 4 کد بالا، باعث می شوند سه متغیر و به ازای هر کدام از آنها نیز دو متد ایجاد شود. برای اختصاص مقدار به متغیر کافیست که یک شیء از کلاس ایجاد کرده و با استفاده از علامت نقطه و مساوی به آن مقداری اختصاص دهید. مثلا برای مقداردهی به متغیر name به صورت زیر عمل می کنیم:
person1.name = "Frank"
برای گرفتن مقدار هم کافیست که نام شیء، علامت نقطه و سپس نام متغیر را بنویسید. کار که در خطوط 14-12 و 24-22 انجام داده ایم. گاهی اوقات ممکن است که شما بخواهید محدودیت هایی برای برخی از متغیرها قرار دهید. مثلا به کاربر اجازه ندهید که مقداری به متغیر age اختصاص دهید. کافیست که نام age را در جلوی متد attr_writer که مسئول مقداردهی است، ننویسید:
attr_writer :name, :height
کد بالا از این ساده تر هم می شود. کافیست که به جای خطوط 3 و 4 از متد attr_accessor به صورت زیر استفاده کنید:
attr_accessor :name, :age, :height
attr_accessor کار دو متد attr_writer و attr_reader را به طور همزمان انجام می دهد.