Menu
Coddy logo textTech

זהות ושוויון

חלק מהיחידה תכנות מונחה עצמים במסלול ה-Ruby של Coddy. שיעור 10 מתוך 57.

משתנה מחזיק הפניה לאובייקט, ולא את האובייקט עצמו. כשמקצים אותו למשתנה אחר, ההפניה מועתקת, ולכן שני השמות מתייחסים לאותו אובייקט:

class Box
  attr_accessor :count

  def initialize
    @count = 0
  end
end

a = Box.new
b = a
b.count += 1
puts a.count

פלט:

1

equal? בודקת אם שתי הפניות מצביעות על אותו אובייקט, ו-object_id הוא המספר הייחודי של כל אובייקט. במחלקות משלך, == עושה זאת כברירת מחדל, ולכן שני אובייקטים בעלי אותם ערכים אינם שווים:

class Point
  attr_reader :x, :y

  def initialize(x, y)
    @x = x
    @y = y
  end
end

a = Point.new(1, 2)
b = Point.new(1, 2)
c = a
puts a == b
puts a.equal?(b)
puts a.equal?(c)
puts a.object_id == c.object_id

פלט:

false
false
true
true

הגדירו את == כך שישווה לפי ערך. פעולות include?, index ו-delete על מערכים משתמשות ב-==, ולכן הן מוצאות גם אובייקטים שווים. בדקו תחילה את המחלקה של other, כדי שהשוואה למספר או ל-nil תחזיר false במקום להיכשל:

class Point
  attr_reader :x, :y

  def initialize(x, y)
    @x = x
    @y = y
  end

  def ==(other)
    other.is_a?(Point) && x == other.x && y == other.y
  end
end

a = Point.new(1, 2)
puts a == Point.new(1, 2)
puts a == 5
puts [Point.new(0, 0), Point.new(1, 2)].include?(a)
puts a.equal?(Point.new(1, 2))

פלט:

true
false
true
false

dup יוצר אובייקט חדש עם עותקים של משתני המופע. הקצאת ערך חדש לעותק אינה משפיעה על המקור, אבל מערך או מחרוזת שבתוכו עדיין משותפים לשניהם, משום שרק ההפניה הועתקה:

class Team
  attr_accessor :name, :players

  def initialize(name)
    @name = name
    @players = []
  end
end

a = Team.new("Reds")
b = a.dup
b.name = "Blues"
b.players << "Ada"
puts a.name
p a.players

פלט:

Reds
["Ada"]
challenge icon

אתגר

קל

השלם את המחלקה Point כך ששתי נקודות בעלות אותם קואורדינטות יהיו שוות באמצעות ==, והשוואה של נקודה לכל דבר אחר תחזיר false. to_s מחזירה (1, 2).

הקוד שסופק קורא נקודות בשורות בפורמט x,y. עבור כל נקודה הוא מדפיס (1, 2) same as first: true או false, ואז שומר רשימה של נקודות שונות באמצעות include? ולבסוף מדפיס distinct: 3 והאם הנקודה הראשונה שווה לטקסט "1,2".

הקוד שלך נמצא בקובץ point.rb. הקובץ main.rb מכיל את קוד הקלט/פלט שסופק ואי אפשר לערוך אותו.

נסו בעצמכם

require_relative 'point'

# קוד קלט/פלט שסופק: יש להשאיר אותו כפי שהוא
input = []
while (line = gets)
  input << line.chomp
end
points = input.map { |line| Point.new(*line.split(",").map(&:to_i)) }
points.each { |pt| puts "#{pt} same as first: #{pt == points[0]}" }
distinct = []
points.each { |pt| distinct << pt unless distinct.include?(pt) }
puts "distinct: #{distinct.size}"
puts "equals text: #{points[0] == input[0]}"
quiz iconבחנו את עצמכם

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

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

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