Đị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:
1equal? 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
falsedup 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"]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]}"
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
1Lớp và đối tượng
Làm việc với tệpĐịnh nghĩa lớpBiến instancePhương thức và selfto_s và inspectÔn tập: thẻ thư viện4Tính đóng gói
Phương thức riêng tưPhương thức được bảo vệPhương thức thiết lập riêng tưBảo vệ trạng tháiÔn tập: máy bán hàng tự động7Tính đa hình và duck typing
Tính đa hìnhDuck typingPhương thức trừu tượngcase và lớpÔn tập: phương thức thanh toán2Phương thức truy cập và self
Phương thức đọc và ghiPhương thức gán tùy chỉnhself trong phương thứcĐịnh danh và tính bằng nhauÔn tập: Danh sách liên hệTự luyện tập: Trình biên dịch Ruby online