الهوية والمساواة
جزء من قسم البرمجة كائنية التوجه في رحلة 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"]التحدي
سهلأكمل الصنف 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]}"
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1الفئات والكائنات
العمل مع الملفاتتعريف الفئاتمتغيرات النسخةالأساليب و selfto_s و inspectمراجعة - بطاقة المكتبة7تعدد الأشكال والكتابة بأسلوب البطة
تعدد الأشكالالكتابة بأسلوب البطةالأساليب المجردةالحالات والفئاتمراجعة - طرق الدفع2المُوَصِّلات و self
القارئات والكاتباتمُعيِّنات مخصّصةself في الأساليبالهوية والمساواةمراجعة - قائمة جهات الاتصال3أساليب ومتغيرات الأصناف
أساليب الأصنافمتغيرات كائنات الأصنافالثوابتأساليب الإنشاءمراجعة - رموز القسائمتدرّب بنفسك: مترجم Ruby عبر الإنترنت