Идентичность и равенство
Часть раздела Объектно-ориентированное программирование путешествия по 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Вывод:
1equal? проверяет, указывают ли две ссылки на один и тот же объект, а 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
falsedup создаёт новый объект с копиями переменных экземпляра. Присваивание нового значения копии не затрагивает оригинал, но массив или строка внутри всё ещё являются общими для обоих объектов, поскольку была скопирована только ссылка:
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"]Задание
ЛегкоДополните класс 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]}"
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Классы и объекты
Работа с файламиОпределение классовПеременные экземпляраМетоды и selfto_s и inspectПовторение — читательский билет4Инкапсуляция
Приватные методыЗащищённые методыПриватные сеттерыЗащита состоянияПовторение — торговый автомат7Полиморфизм и утиная типизация
ПолиморфизмУтиная типизацияАбстрактные методыcase и классыПовторение — способы оплаты10Шаблоны проектирования, часть 2
Делегирование с помощью ForwardableШаблон декоратораШаблон строителяШаблон состояния2Аксессоры и self
Чтение и записьПользовательские сеттерыself в методахИдентичность и равенствоПовторение — список контактов5Наследование
ПодклассыПереопределение методовВызов superis_a? и предкиПовторение — расчёт зарплаты сотрудников8Специальные методы
Равенство и хешированиеМетоды операторовИндексация и добавлениеПользовательские коллекцииПовторение — дроби11Проект: Управление библиотекой
Книги и читателиВыдача книг3Методы и переменные классов
Методы классовПеременные экземпляра классаКонстантыФабричные методыПовторение — коды купонов6Модули и примеси
Модули и includeРасширение объектовМодуль ComparableМодуль EnumerableПовторение — спортивная лига9Паттерны проектирования. Часть 1
Паттерн «Одиночка»Фабричный паттернПаттерн «Наблюдатель»Паттерн «Стратегия»Потренируйтесь самостоятельно: Онлайн-компилятор Ruby