Menu
CoddyTech

Identité et égalité

Fait partie de la section Programmation orientée objet du Journey Ruby de Coddy. Leçon 10 sur 57.

Une variable contient une référence à un objet, et non l’objet lui-même. L’affecter à une autre variable copie la référence, de sorte que les deux noms font ensuite référence au même objet :

class Box
  attr_accessor :count

  def initialize
    @count = 0
  end
end

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

Résultat :

1

equal? demande si deux références pointent vers le même objet, et object_id est le numéro unique de chaque objet. Pour vos propres classes, == fait la même chose par défaut, donc deux objets ayant les mêmes valeurs ne sont pas égaux :

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

Résultat :

false
false
true
true

Définissez == pour comparer les valeurs. Sur les tableaux, include?, index et delete utilisent == ; ils trouvent donc aussi les objets égaux. Vérifiez d’abord la classe de other, afin qu’une comparaison avec un nombre ou nil renvoie false au lieu d’échouer :

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))

Résultat :

true
false
true
false

dup crée un nouvel objet avec des copies des variables d’instance. Attribuer une nouvelle valeur à la copie laisse l’original intact, mais un tableau ou une chaîne qu’elle contient reste partagé entre les deux, car seule la référence a été copiée :

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

Résultat :

Reds
["Ada"]
challenge icon

Défi

Facile

Complétez la classe Point afin que deux points ayant les mêmes coordonnées soient égaux avec ==, et que la comparaison d’un point avec n’importe quoi d’autre renvoie false. to_s renvoie (1, 2).

Le code fourni lit les points sous forme de lignes x,y. Pour chaque point, il affiche (1, 2) same as first: true ou false, puis conserve une liste de points distincts à l’aide de include? et affiche enfin distinct: 3 ainsi que le résultat indiquant si le premier point est égal au texte "1,2".

Votre code doit être placé dans point.rb. main.rb contient le code fourni pour les entrées et les sorties et ne peut pas être modifié.

Essayez vous-même

require_relative 'point'

# Code d'entrée/sortie fourni : conservez-le tel quel
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 iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation orientée objet

Entraînez-vous par vous-même : Compilateur Ruby en ligne