وراثت

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

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

 1: class Parent
 2:   attr_accessor :message
 3: 
 4:   def initialize(message)
 5:     @message = message
 6:   end
 7: end
 8: 
 9: class Child < Parent
10: 
11: end
12: 
13: myParent = Parent.new("Message from parent.")
14: myChild  = Child.new("Message from Child.")
15: 
16: puts myParent.message
17: puts myChild.message
18: 
19: myParent.message = "Modified message of the parent."
20: puts myParent.message
21: 
22: myChild.message = "Modified message of the child."
23: puts myChild.message
Message from parent.
Message from Child.
Modified message of the parent.
Modified message of the child.

در این مثال دو کلاس با نامهای Parent (خطوط 7-1) و Child (خطوط 11-9) تعریف شده است. در کلاس Parent یک متغیر به نام message تعریف کرده ایم که هم می توانیم با استفاده از سازنده و هم از طریق ایجاد شیء از کلاس آن را مقدار دهی کنیم. در خط 9 که موضوع اصلی این درس است، کلاس Child از کلاس Parent ارث بری کرده است:

class Child < Parent

همانطور که در خط 9 مشاهده می کنید، براحتی می‌توان با قرار دادن > بعد از نام کلاس و سپس نوشتن نام کلاسی که از آن ارث بری می‌شود (کلاس پایه) این کار را انجام داد. وقتی از وراثت در کلاسها استفاده می‌کنیم، هم سازنده کلاس مشتق و هم سازنده پیشفرض کلاس پایه هر دو اجرا می‌شوند. اگر هنگام صدا زدن سازنده کلاس مشتق بخواهیم سازنده کلاس پایه را صدا بزنیم باید از کلمه کلیدی super استفاده کنیم. نحوه صدا زدن سازنده کلاس پایه در کلاس فرزند به صورت زیر است:

def initialize
    super
end

در کل این خط بدین معنی است که تمام کدهای بدنه سازنده کلاس پایه را می خواهم در کلاس فرزند داشته باشم. توجه کنید که کلمه super را باید در داخل متد initilize بنویسید. به مثال زیر توجه کنید:

 1: class Parent
 2:   def initialize
 3:     puts "Parent Constructor!"
 4:   end
 5: end
 6: 
 7: class Child < Parent
 8:   def initialize
 9:     puts "Child Constructor!"
10:     super
11:   end
12: end
13: 
14: child = Child.new
Child Constructor!
Parent Constructor!

در کل بالا در خط 10 سازنده کلاس پایه را در کلاس فرزند فراخوانی کرده ایم. در نتیجه وقتی در خط 14 یک شیء از کلاس فرزند ایجاد می کنیم، هم پیغام مربوط به سازنده خودش (خط 9) و هم پیغام مربوط به سازنده کلاس پایه (خط 3) چاپ می شود. به کد ابتدای درس بر می گردیم. همانطور که اشاره شد، در کلاس Parent یک متغیر به نام message تعریف کرده ایم که هم می توانیم با استفاده از سازنده و هم ایجاد شیء از کلاس، آن را مقدار دهی کنیم. در خطوط 13 و 14 دو شیء از دو کلاس می سازیم و سپس در داخل پرانتز هم دو رشته می نویسیم که در داخل سازنده ها به متغیر message اختصاص داده شوند. در نتیجه در خطوط 13 و 14 می توانیم به راحتی مقدار موجود در متغیر message مربوط به هر دو کلاس را چاپ کنیم. روش دوم برای مقداردهی به متغیر message، دسترسی مستقیم به متغیر و مقداردهی آن است که این کار را در خطوط 19 و 22 انجام داده ایم.