Menu
CoddyTech

Định danh và tính bằng nhau

Thuộc phần Lập trình hướng đối tượng trong hành trình Ruby của Coddy. Bài học 10 trên 57.

Biến giữ một tham chiếu đến một đối tượng, chứ không phải chính đối tượng đó. Khi gán biến đó cho một biến khác, thao tác này sẽ sao chép tham chiếu, nên sau đó cả hai tên đều tham chiếu đến cùng một đối tượng:

class Box
  attr_accessor :count

  def initialize
    @count = 0
  end
end

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

Đầu ra:

1

equal? kiểm tra hai tham chiếu có trỏ đến cùng một đối tượng hay không, còn object_id là số định danh riêng của mỗi đối tượng. Với các lớp do bạn tự tạo, theo mặc định, == cũng hoạt động như vậy, nên hai đối tượng có cùng giá trị vẫn không bằng nhau:

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

Đầu ra:

false
false
true
true

Định nghĩa == để so sánh theo giá trị. Các phương thức include?, index và delete trên mảng dùng ==, nên chúng cũng tìm được các đối tượng có giá trị bằng nhau. Kiểm tra lớp của other trước, để khi so sánh với một số hoặc nil, kết quả là false thay vì gây lỗi:

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

Đầu ra:

true
false
true
false

dup tạo một đối tượng mới với các bản sao của biến thực thể. Gán giá trị mới cho bản sao không làm thay đổi đối tượng gốc, nhưng mảng hoặc chuỗi bên trong vẫn được chia sẻ giữa hai đối tượng vì chỉ có tham chiếu được sao chép:

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

Đầu ra:

Reds
["Ada"]
challenge icon

Thử thách

Dễ

Hoàn thiện lớp Point để hai điểm có cùng tọa độ bằng nhau khi so sánh bằng ==, còn khi so sánh một điểm với bất kỳ thứ gì khác thì trả về false. to_s trả về (1, 2).

Code được cung cấp đọc các điểm từ những dòng có dạng x,y. Với mỗi điểm, code in ra (1, 2) same as first: true hoặc false, sau đó lưu danh sách các điểm riêng biệt bằng include? và cuối cùng in ra distinct: 3 cùng với việc điểm đầu tiên có bằng văn bản "1,2" hay không.

Code của bạn nằm trong point.rb. main.rb chứa code đầu vào/đầu ra được cung cấp và bạn không thể chỉnh sửa tệp này.

Tự làm thử

require_relative 'point'

# Đoạn code đầu vào/đầu ra có sẵn: giữ nguyên
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 iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch Ruby online