خواص (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 را به طور همزمان انجام می دهد.