الهوية والمساواة
جزء من قسم البرمجة كائنية التوجه في رحلة 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 عبر الإنترنت