Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

الهوية والمساواة

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