Darsliklar Ruby Polimorfizm

Ruby Ruby Polimorfizm

Polimorfizm — OOP ning uchinchi ustuni: bitta chaqiruv turli obyektlarda turlicha ishlashi. C++ kabi statik tillarda buning uchun virtual kalit so’zi kerak bo’ladi, Ruby’da esa bu standart xatti-harakat — hech qanday maxsus e’lon talab qilinmaydi.

Polimorfizmbir xil metod chaqiruvining turli sinf obyektlarida o’ziga xos natija berish qobiliyati. Ruby’da barcha metod chaqiruvlari dinamik hal qilinadi — obyektning haqiqiy sinfiga qarab to’g’ri metod avtomatik tanlanadi.

Meros orqali polimorfizm

Bir xil metod nomi turli bola sinflarda turlicha ishlaydi — hech qanday qo’shimcha kalit so’zsiz:

class Hayvon
  def ovoz
    "Noma'lum ovoz"
  end
end

class Mushuk < Hayvon
  def ovoz
    "Miyov"
  end
end

class It < Hayvon
  def ovoz
    "Vov"
  end
end

[Hayvon.new, Mushuk.new, It.new].each do |hayvon|
  puts hayvon.ovoz
end
Noma'lum ovoz
Miyov
Vov

Bir xil hayvon.ovoz chaqiruvi har bir obyektda o’zining sinfiga mos natija berdi — C++’dagi virtual, Ruby’da hamma metod uchun tabiiy ravishda ishlaydi.

Duck typing — merosdan tashqari polimorfizm

Ruby’da polimorfizm uchun umumiy ota sinf shart emas — muhimi, obyekt kerakli metodga javob berishi:

class Papagay
  def ovoz
    "Salom!"
  end
end

class Signalizatsiya
  def ovoz
    "Wii-uuu!"
  end
end

[Papagay.new, Signalizatsiya.new].each do |narsa|
  puts narsa.ovoz
end
Salom!
Wii-uuu!

Papagay va Signalizatsiya — bir-biriga umuman aloqasi yo’q sinflar, umumiy ota ham yo’q. Lekin ikkalasida ham ovoz metodi bor bo’lgani uchun ular bir xil kodda muammosiz ishlatildi. Bu — duck typing: “agar u o’rdakdek yursa va o’rdakdek g’oz-g’oz qilsa, u o’rdak hisoblanadi” tamoyili. Ruby’da tur emas, xatti-harakat (qaysi metodga javob bera olishi) muhim.

respond_to? — obyekt metodga javob bera oladimi

Duck typing bilan ishlaganda, obyektning kerakli metodga ega ekanini oldindan tekshirish foydali:

narsalar = [Papagay.new, "oddiy satr", 42]

narsalar.each do |narsa|
  if narsa.respond_to?(:ovoz)
    puts narsa.ovoz
  else
    puts "#{narsa.class} ovoz chiqara olmaydi"
  end
end
Salom!
String ovoz chiqara olmaydi
Integer ovoz chiqara olmaydi

respond_to?(:ovoz) — obyektda ovoz metodi bor-yo’qligini xavfsiz tekshiradi, mos kelmasa dastur qulamaydi. Bu duck typing’ni amaliyotda xavfsiz qo’llashning standart usuli.

Statik va dinamik polimorfizm farqi

Ikki yondashuvni jadvalda solishtiramiz:

Jihat C++ (statik til) Ruby (dinamik til)
Kerakli e’lon virtual kalit so’zi shart emas — standart
Umumiy ota sinf odatda talab qilinadi shart emas (duck typing)
Tekshiruv vaqti kompilyatsiyada ijro paytida (runtime)

Ruby’ning bu erkinligi kodni moslashuvchan qiladi, ammo mas’uliyatni ham oshiradi: xato faqat dastur ishga tushgach, aynan o’sha metod chaqirilganda ma’lum bo’ladi.