Атрибуты и методы доступа
Атрибуты - это компоненты класса, к которым можно обращаться извне объекта.Они известны как свойства во многих других языках программирования.Их значения доступны с помощью «точечной нотации», как в object_name.attribute_name.В отличие от Python и некоторых других языков, Ruby не позволяет обращаться к переменным экземпляра напрямую из-за пределов объекта.
class Car
def initialize
@wheels = 4 # This is an instance variable
end
end
c = Car.new
c.wheels # Output: NoMethodError: undefined method `wheels' for #<Car:0x00000000d43500>
В приведенном выше примере c является экземпляром (объектом) класса Car.Мы безуспешно пытались прочитать значение переменной экземпляра колеса снаружи объекта.Случилось так, что Ruby попытался вызвать метод с именем wheel внутри объекта c, но такой метод не был определен.Вкратце, имя_объекта.attribute_name пытается вызвать метод с именем имя_атрибута внутри объекта.Чтобы получить доступ к значению переменной wheel извне, нам нужно реализовать метод экземпляра с таким именем, который будет возвращать значение этой переменной при вызове.Это называется методом доступа.В общем контексте программирования обычным способом доступа к переменной экземпляра вне объекта является реализация методов доступа, также известных как методы получения и установки.Метод получения позволяет считывать значение переменной, определенной в классе, извне, а метод установки позволяет записывать ее извне.
В следующем примере мы добавили методы получения и установки кКласс автомобиля для доступа к переменным колесам снаружи объекта.Это не «Рубиновый способ» определения методов получения и установки;он служит только для иллюстрации того, что делают методы получения и установки.
class Car
def wheels # getter method
@wheels
end
def wheels=(val) # setter method
@wheels = val
end
end
f = Car.new
f.wheels = 4 # The setter method was invoked
f.wheels # The getter method was invoked
# Output: => 4
Приведенный выше пример работает, и аналогичный код обычно используется для создания методов получения и установки в других языках.Тем не менее, Ruby предоставляет более простой способ сделать это: три встроенных метода, называемые attr_reader, attr_writer и attr_acessor.Метод attr_reader делает переменную экземпляра доступной для чтения извне, attr_writer делает ее доступной для записи, а attr_acessor делает ее читаемой и доступной для записи.
Приведенный выше пример можно переписать так:
class Car
attr_accessor :wheels
end
f = Car.new
f.wheels = 4
f.wheels # Output: => 4
В приведенном выше примере атрибут wheel будет доступен для чтения и записи извне объекта.Если бы вместо attr_accessor мы использовали attr_reader, он был бы доступен только для чтения.Если бы мы использовали attr_writer, он был бы только для записи.Эти три метода сами по себе не являются методами получения и установки, но при вызове они создают методы получения и установки для нас.Это методы, которые динамически (программно) генерируют другие методы;это называется метапрограммирование.
Первый (более длинный) пример, в котором не используются встроенные методы Ruby, должен использоваться только тогда, когда в методах get и set требуется дополнительный код.Например, для метода установки может потребоваться проверить данные или выполнить некоторые вычисления, прежде чем присваивать значение переменной экземпляра.
Доступ к переменным экземпляра (чтение и запись) возможен извне объекта с помощью встроенных методов instance_variable_get и instance_variable_set.Тем не менее, это редко оправдано и, как правило, является плохой идеей, так как обход инкапсуляции может привести к разного рода разрушениям.