Menu
CoddyTech

身份与相等性

本课属于 Coddy Ruby 学习旅程的“面向对象编程”单元。第 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 在线编译器