זהות ושוויון
חלק מהיחידה תכנות מונחה עצמים במסלול ה-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פלט:
1equal? בודקת אם שתי הפניות מצביעות על אותו אובייקט, ו-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
falsedup יוצר אובייקט חדש עם עותקים של משתני המופע. הקצאת ערך חדש לעותק אינה משפיעה על המקור, אבל מערך או מחרוזת שבתוכו עדיין משותפים לשניהם, משום שרק ההפניה הועתקה:
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"]אתגר
קלהשלם את המחלקה 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]}"
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
3מתודות ומשתנים של מחלקה
מתודות של מחלקהמשתני מופע של מחלקהקבועיםמתודות ליצירת מופעיםסיכום – קודי קופוןתרגלו בעצמכם: קומפיילר Ruby אונליין