שיטות אופרטורים
חלק מהיחידה תכנות מונחה עצמים במסלול ה-Ruby של Coddy. שיעור 38 מתוך 57.
רוב האופרטורים ב-Ruby הם מתודות. a + b קורא ל-a.+(b), לכן מחלקה מגדירה את + כמו כל מתודה אחרת. פעולות חשבון על אובייקטים של ערכים מחזירות אובייקט חדש ומשאירות את שני האופרנדים ללא שינוי:
class Vector
attr_reader :x, :y
def initialize(x, y)
@x = x
@y = y
end
def +(other)
Vector.new(x + other.x, y + other.y)
end
def to_s
"(#{x}, #{y})"
end
end
a = Vector.new(1, 2)
b = Vector.new(3, 4)
puts a + b
puts aפלט:
(4, 6)
(1, 2)האופרנד הימני יכול להיות סוג אחר של ערך, כגון מספר לצורך שינוי קנה מידה. מינוס אונרי הוא המתודה -@:
class Vector
attr_reader :x, :y
def initialize(x, y)
@x = x
@y = y
end
def -(other)
Vector.new(x - other.x, y - other.y)
end
def *(factor)
Vector.new(x * factor, y * factor)
end
def -@
Vector.new(-x, -y)
end
def to_s
"(#{x}, #{y})"
end
end
v = Vector.new(3, 4)
puts v * 2
puts v - Vector.new(1, 1)
puts(-v)פלט:
(6, 8)
(2, 3)
(-3, -4)ברגע ש־+ קיים, גם += עובד, כי a += b פירושו a = a + b. גם sum עובד כשנותנים לו ערך התחלתי מהמחלקה שלך:
class Money
attr_reader :cents
def initialize(cents)
@cents = cents
end
def +(other)
Money.new(cents + other.cents)
end
def to_s
format("$%.2f", cents / 100.0)
end
end
total = Money.new(0)
total += Money.new(250)
total += Money.new(199)
puts total
puts [Money.new(100), Money.new(5)].sum(Money.new(0))פלט:
$4.49
$1.05גם <=> הוא אופרטור. בשילוב עם Comparable, הוא מאפשר להשוות בין אובייקטים מסוג Money ולמיין אותם, ואופרטור יכול לדחות אופרנד שאינו תואם באמצעות העלאת חריגה, כמו שמספרים עושים:
class Money
include Comparable
attr_reader :cents, :currency
def initialize(cents, currency)
@cents = cents
@currency = currency
end
def +(other)
raise ArgumentError, "cannot add #{other.currency} to #{currency}" unless other.currency == currency
Money.new(cents + other.cents, currency)
end
def <=>(other)
cents <=> other.cents
end
end
puts Money.new(500, "EUR") > Money.new(300, "EUR")
begin
Money.new(1, "EUR") + Money.new(1, "USD")
rescue ArgumentError => e
puts e.message
endפלט:
true
cannot add USD to EURאתגר
קלהשלם את המחלקה Vector. הגדר את + ואת - עבור שני וקטורים, את * עבור וקטור ומספר, מינוס אונרי -@, את == להשוואת שתי הקואורדינטות, ואת to_s, שמחזירה (4, 6). length מחזירה את אורך הווקטור בעזרת Math.sqrt.
הקוד שסופק קורא ביטויים: 1,2 + 3,4, 1,2 - 3,4, 1,2 * 3, neg 1,2 ו-1,2 == 1,2. הוא מדפיס כל תוצאה, ובמקרה של תוצאות שהן וקטורים גם את length 7.21 עם שתי ספרות אחרי הנקודה העשרונית.
הקוד שלך ייכתב ב-vector.rb. הקובץ main.rb מכיל את קוד הקלט/פלט שסופק ואי אפשר לערוך אותו.
נסו בעצמכם
require_relative 'vector'
# קוד קלט/פלט שסופק: יש להשאיר אותו כפי שהוא
input = []
while (line = gets)
input << line.chomp
end
def vec(text)
Vector.new(*text.split(",").map(&:to_i))
end
input.each do |line|
parts = line.split
result = if parts[0] == "neg" then -vec(parts[1])
else
a = vec(parts[0])
case parts[1]
when "+" then a + vec(parts[2])
when "-" then a - vec(parts[2])
when "*" then a * parts[2].to_i
else a == vec(parts[2])
end
end
puts result
puts format("length %.2f", result.length) if result.is_a?(Vector)
end
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
3מתודות ומשתנים של מחלקה
מתודות של מחלקהמשתני מופע של מחלקהקבועיםמתודות ליצירת מופעיםסיכום – קודי קופוןתרגלו בעצמכם: קומפיילר Ruby אונליין