טיפוס ברווז
חלק מהיחידה תכנות מונחה עצמים במסלול ה-Ruby של Coddy. שיעור 33 מתוך 57.
Ruby לא בודקת את המחלקה של אובייקט לפני קריאה למתודה; היא רק דורשת שלאובייקט תהיה המתודה. "אם הוא הולך כמו ברווז ומגעגע כמו ברווז, הוא ברווז." זהו טיפוס ברווז: אפשר להשתמש באותה דרך במחלקות שאין להן מחלקת־על משותפת:
class Duck
def speak
"Quack"
end
end
class Robot
def speak
"Beep"
end
end
class Radio
def speak
"...news..."
end
end
[Duck.new, Robot.new, Radio.new].each { |thing| puts thing.speak }פלט:
Quack
Beep
...news...גם מחלקות מובנות משתתפות. שיטה שמשתמשת רק ב־<< עובדת עם מערך, מחרוזת או כל אובייקט שלך שמגדיר את <<:
class Tally
attr_reader :count
def initialize
@count = 0
end
def <<(_item)
@count += 1
self
end
end
def export(items, target)
items.each { |item| target << item.to_s }
target
end
p export([1, 2], [])
p export([1, 2], +"")
puts export([1, 2, 3], Tally.new).countפלט:
["1", "2"]
"12"
3respond_to?(:name) בודקת אם לאובייקט יש מתודה ציבורית, בלי לקרוא לה. השתמשו בה כשייתכן שאובייקט תומך בתכונה אופציונלית או לא:
class Printer
def print_page(text)
"printing #{text}"
end
end
class Scanner
end
[Printer.new, Scanner.new].each do |device|
if device.respond_to?(:print_page)
puts device.print_page("report")
else
puts "#{device.class} cannot print"
end
endפלט:
printing report
Scanner cannot printכאשר לאובייקט אין את השיטה, הקריאה גורמת ל־NoMethodError, שההודעה שלו מציינת את השיטה ואת האובייקט. טיפוס ברווז מסתמך על כך שכל אובייקט שמועבר עונה לשיטות שנשלחות אליו:
def loudest(things)
things.map(&:speak).max_by(&:size)
end
class Cat
def speak
"Meow"
end
end
puts loudest([Cat.new, Cat.new])
begin
loudest([Cat.new, 42])
rescue NoMethodError => e
puts e.message
endפלט:
Meow
undefined method `speak' for an instance of Integerאתגר
קלהשלימו את המחלקות Printer ו־LineCounter ואת פונקציית העזר export(items, target) בקובץ functions.rb. הפונקציה export שולחת כל פריט אל היעד באמצעות target << item.to_s ומחזירה את היעד. Printer#<< מדפיסה את הטקסט עם מספר שורה, 1: text, ומחזירה את המדפסת. LineCounter#<< סופרת שורות ותווים ומחזירה את המונה; הפונקציה to_s שלה מחזירה 3 lines, 12 chars.
הקוד שסופק קורא פריטים ומייצא אותם למערך (שמוצג באמצעות p), למחרוזת חדשה (שמוצגת באמצעות p), אל Printer ואל LineCounter (שמוצג באמצעות puts).
הקוד שלך ייכתב בקבצים printer.rb, line_counter.rb ו־functions.rb. הקובץ main.rb מכיל את קוד הקלט/פלט שסופק, ואי אפשר לערוך אותו.
נסו בעצמכם
require_relative 'printer'
require_relative 'line_counter'
require_relative 'functions'
# קוד קלט/פלט שסופק: יש להשאיר אותו כפי שהוא
input = []
while (line = gets)
input << line.chomp
end
p export(input, [])
p export(input, +"")
export(input, Printer.new)
puts export(input, LineCounter.new)
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
3מתודות ומשתנים של מחלקה
מתודות של מחלקהמשתני מופע של מחלקהקבועיםמתודות ליצירת מופעיםסיכום – קודי קופוןתרגלו בעצמכם: קומפיילר Ruby אונליין