טיפוס ברווז
חלק מהיחידה תכנות מונחה עצמים במסלול ה-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 אונליין