Самым главным является метод equal?(унаследованный от класса Object); он возвращает true, если вызывающий объект и параметр имеют один и тот же идентификатор объекта. Это фундаментальный аспект семантики объектов, поэтому переопределять его не следует.
Самым распространенным способом проверки на равенство является старый добрый оператор ==, который сравнивает значения вызывающего объекта и аргумента. Наверно, интуитивно это наиболее очевидный способ.
Следующим в шкале абстракции стоит метод eql?— тоже часть класса Object. (На самом деле метод eql?реализован в модуле Kernel, который подмешивается в Object.) Как и оператор ==, этот метод сравнивает значения вызывающего объекта и аргумента, но несколько более строго. Например, разные числовые объекты при сравнении с помощью ==приводятся к общему типу, но метод eql?никогда не считает объекты разных типов равными.
flag1 = (1 == 1.0) # true
flag2 = (1.eql?(1.0)) # false
Метод eql?существует по одной-единственной причине: для сравнения значений ключей хэширования. Если вы хотите переопределить стандартное поведение Ruby при использовании объектов в качестве ключей хэша, то переопределите методы eql?и hash.
Любой объект реализует еще два метода сравнения. Метод ===применяется для сравнения проверяемого значения в предложении caseс каждым селектором: selector===target. Хотя правило на первый взгляд кажется сложным, на практике оно делает предложения caseв Ruby интуитивно очевидными. Например, можно выполнить ветвление по классу объекта:
case an_object
when String
puts "Это строка."
when Numeric
puts "Это число."
else
puts "Это что-то совсем другое."
end
Эта конструкция работает, потому что в классе Moduleреализован метод ===, проверяющий, принадлежит ли параметр тому же классу, что вызывающий объект (или одному из его предков). Поэтому, если an_object— это строка «cat», выражение string === an_objectокажется истинным и будет выбрана первая ветвь в предложении case.
Наконец, в Ruby реализован оператор сопоставления с образцом =~. Традиционно он применяется для сопоставления строки с регулярным выражением. Но если вы найдете ему применение в других классах, то можете переопределить.
У операторов ==и =~есть противоположные формы: !=и !~соответственно. Внутри они реализованы путем обращения значения основной формы. Это означает, что если, например, вы реализовали метод ==, то метод !=получаете задаром.
11.1.8. Управление доступом к методам
В Ruby объект определяется, прежде всего, своим интерфейсом: теми методами, которые он раскрывает внешнему миру. Но при написании класса часто возникает необходимость во вспомогательных методах, вызывать которые извне класса опасно. Тут-то и приходит на помощь метод privateкласса Module.
Использовать его можно двумя способами. Если в теле класса или модуля вы вызовете privateбез параметров, то все последующие методы будут закрытыми в данном классе или модуле. Если же вы передадите ему список имен методов (в виде символов), то эти и только эти методы станут закрытыми. В листинге 11.5 показаны оба варианта.
Листинг 11.5. Закрытые методы
class Bank
def open_safe
# ...
end
def close_safe
# ...
end
private :open_safe, :close_safe
def make_withdrawal(amount)
if access_allowed
open_safe
get_cash(amount)
close_safe
end
end
# Остальные методы закрытые.
private
def get_cash
# ...
end
def access_allowed
# ...
end
end
Поскольку методы из семейства attrпросто определяют методы, метод privateопределяет и видимость атрибутов.
Реализация метода privateможет показаться странной, но на самом деле она весьма хитроумна. К закрытым методам нельзя обратиться, указав вызывающий объект; они вызываются только от имени неявно подразумеваемого объекта self. То есть вызвать закрытый метод из другого объекта не удастся: просто не существует способа указать объект, от имени которого данный метод вызывается. Заодно это означает, что закрытые методы доступны подклассам того класса, в котором определены, но опять же в рамках одного объекта.
Модификатор доступа protectedналагает меньше ограничений. Защищенные методы доступны только экземплярам того класса, в котором определены, и его подклассов. Для защищенного метода разрешается указывать вызывающий объект, так что к ним можно обращаться из других объектов (при условии, что вызывающий и вызываемый объекты принадлежат одному классу). Обычно защищенные методы применяются для определения методов доступа, чтобы два объекта одного типа могли взаимодействовать. В следующем примере объекты класс Personможно сравнивать по возрасту, но сам возраст недоступен вне класса Person:
Читать дальше
Конец ознакомительного отрывка
Купить книгу