Menu
Coddy logo textTech

שיטות אופרטורים

חלק מהיחידה תכנות מונחה עצמים במסלול ה-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
challenge icon

אתגר

קל

השלם את המחלקה 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
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר Ruby אונליין