Что такое attr accessor в Ruby?
Мне трудно понять attr_accessor
в Ruby. Кто-нибудь может мне это объяснить?
18 ответов
Допустим у вас есть класс Person
.
class Person
end
person = Person.new
person.name # => no method error
очевидно, мы никогда не определяется методом name
. Давайте сделаем это.
class Person
def name
@name # simply returning an instance variable @name
end
end
person = Person.new
person.name # => nil
person.name = "Dennis" # => no method error
Ага, мы можем прочитать имя, но это не значит, что мы можем назначить имя. Это два разных метода. Первая называется читатель и последний называется писатель. Мы еще не создали писателя, так что давайте сделаем это.
class Person
def name
@name
end
def name=(str)
@name = str
end
end
person = Person.new
person.name = 'Dennis'
person.name # => "Dennis"
потрясающе. Теперь мы можем писать и читать переменные экземпляра @name
использование методов чтения и записи. Кроме того, это делается так часто, зачем тратить время на написание этих методов каждый раз? Мы можем сделать это проще.
class Person
attr_reader :name
attr_writer :name
end
даже это может повторяться. Когда вы хотите, чтобы и читатель и писатель просто использовать accessor!
class Person
attr_accessor :name
end
person = Person.new
person.name = "Dennis"
person.name # => "Dennis"
работает так же! И угадайте, что: переменная экземпляра @name
в нашем лице объект будет установлен так же, как когда мы сделали это вручную, поэтому вы можете использовать его в других методах.
class Person
attr_accessor :name
def greeting
"Hello #{@name}"
end
end
person = Person.new
person.name = "Dennis"
person.greeting # => "Hello Dennis"
вот он. Чтобы понять, как attr_reader
, attr_writer
и attr_accessor
методы фактически генерируют методы для вас, читают другие ответы, книги, ruby docs.
attr_accessor is метод. (Ссылка должна дать больше информации о том, как она работает - посмотрите на созданные пары методов, и учебник должен показать вам, как ее использовать.)
фишка в том, что class
is не определение в Ruby (это "просто определение" на таких языках, как C++ и Java), но это выражения. Именно во время этой оценки, когда attr_accessor
метод вызывается что, в свою очередь, изменяет текущий класс-помните неявный приемник:self.attr_accessor
, где self
является" открытым " объектом класса на данный момент.
необходимость attr_accessor
и друзьям, это, так:
Ruby, как и Smalltalk, не позволяет обращаться к переменным экземпляра вне методов1 для этого объекта. То есть переменные экземпляра не могут быть доступны в
x.y
форма, как обычно, скажем, Java или даже Python. В Рубиy
is всегда берется как сообщение для отправки (или"метод вызова"). Таким образомattr_*
методы создают обертки, которые прокси экземпляр@variable
доступ через динамически созданные методы.шаблонный отстой
надеюсь, это прояснит некоторые из маленьких деталей. Удачи в кодировании.
1 это не совсем так, и есть некоторые "техники" по этой, но нет поддержки синтаксиса доступ к переменной" public instance".
attr_accessor
(как указано в @pst) просто метод. Что он делает, так это создает больше методов для вас.
так этот код:
class Foo
attr_accessor :bar
end
эквивалентно этому коду:
class Foo
def bar
@bar
end
def bar=( new_value )
@bar = new_value
end
end
вы можете написать такой метод самостоятельно в Ruby:
class Module
def var( method_name )
inst_variable_name = "@#{method_name}".to_sym
define_method method_name do
instance_variable_get inst_variable_name
end
define_method "#{method_name}=" do |new_value|
instance_variable_set inst_variable_name, new_value
end
end
end
class Foo
var :bar
end
f = Foo.new
p f.bar #=> nil
f.bar = 42
p f.bar #=> 42
attr_accessor
очень просто:
attr_accessor :foo
ярлык для:
def foo=(val)
@foo = val
end
def foo
@foo
end
это не более чем геттер/сеттер для объекта
Это просто метод, который определяет методы getter и setter для переменных экземпляра. Примером реализации может быть:
def self.attr_accessor(*names)
names.each do |name|
define_method(name) {instance_variable_get("@#{name}")} # This is the getter
define_method("#{name}=") {|arg| instance_variable_set("@#{name}", arg)} # This is the setter
end
end
Я также столкнулся с этой проблемой и написал несколько пространный ответ на этот вопрос. Есть некоторые отличные ответы на это уже, но кто ищет больше разъяснений, я надеюсь, что мой ответ может помочь
Initialize Метод
Initialize позволяет устанавливать данные в экземпляр объекта при создании экземпляра, а не устанавливать их в отдельной строке кода при каждом создании нового экземпляра класса.
class Person
attr_accessor :name
def initialize(name)
@name = name
end
def greeting
"Hello #{@name}"
end
end
person = Person.new("Denis")
puts person.greeting
In в приведенном выше коде мы устанавливаем имя "Denis" с помощью метода initialize, передавая Dennis через параметр Initialize. Если бы мы хотели установить имя без метода initialize, мы могли бы сделать так:
class Person
attr_accessor :name
# def initialize(name)
# @name = name
# end
def greeting
"Hello #{name}"
end
end
person = Person.new
person.name = "Dennis"
puts person.greeting
в приведенном выше коде мы устанавливаем имя, вызывая метод attr_accessor setter с помощью person.имя, а не установка значений при инициализации объекта.
оба "метода" выполнения этой работы, но initialize экономит наше время и строки программного кода.
это единственное задание инициализации. Вы не можете вызвать initialize как метод. Чтобы фактически получить значения объекта экземпляра, вам нужно использовать геттеры и сеттеры (attr_reader (get), attr_writer(set) и attr_accessor(оба)). Подробнее об этом см. ниже.
геттеры, сеттеры (attr_reader, attr_writer, attr_accessor)
Getters, attr_reader: вся цель геттера-вернуть значение конкретного экземпляра переменная. Посетите пример кода ниже для разбивки по этому.
class Item
def initialize(item_name, quantity)
@item_name = item_name
@quantity = quantity
end
def item_name
@item_name
end
def quantity
@quantity
end
end
example = Item.new("TV",2)
puts example.item_name
puts example.quantity
в приведенном выше коде вы вызываете методы "item_name" и "quantity"на экземпляре элемента "example". Тот " ставит пример.item_name" и "пример.quantity "вернет (или" получит") значение параметров, которые были переданы в" пример", и отобразит их на экране.
к счастью, в Ruby есть свойственный метод, который позволяет нам писать этот код более кратко; способ attr_reader. См. код ниже;
class Item
attr_reader :item_name, :quantity
def initialize(item_name, quantity)
@item_name = item_name
@quantity = quantity
end
end
item = Item.new("TV",2)
puts item.item_name
puts item.quantity
этот синтаксис работает точно так же, только он спасает нас шесть строк кода. Представьте, если бы у вас было еще 5 состояний, относящихся к классу элементов? Код быстро станет длинным.
Setters, attr_writer: то, что пересекло меня сначала с методами setter, заключается в том, что в моих глазах он, казалось, выполнял идентичную функцию с методом initialize. Ниже я объясняю разницу, основанную на моем понимании;
As как указано выше, метод initialize позволяет задавать значения для экземпляра объекта при создании объекта.
но что, если вы хотите установить значения позже, после создания экземпляра, или изменить их после их инициализации? Это будет сценарий, в котором вы будете использовать метод setter. ВОТ В ЧЕМ РАЗНИЦА. Вам не нужно "устанавливать" определенное состояние, когда вы используете метод attr_writer изначально.
ниже код является примером использование метода setter для объявления значения item_name для этого экземпляра класса Item. Обратите внимание, что мы продолжаем использовать метод getter attr_reader, чтобы получить значения и распечатать их на экране, на случай, если вы хотите протестировать код самостоятельно.
class Item
attr_reader :item_name
def item_name=(str)
@item_name = (str)
end
end
приведенный ниже код является примером использования attr_writer, чтобы еще раз сократить наш код и сэкономить нам время.
class Item
attr_reader :item_name
attr_writer :item_name
end
item = Item.new
puts item.item_name = "TV"
код ниже является повторением примера инициализации выше того, где мы находимся использование initialize для установки значения объектов item_name при создании.
class Item
attr_reader :item_name
def initialize(item_name)
@item_name = item_name
end
end
item = Item.new("TV")
puts item.item_name
attr_accessor: выполняет функции как attr_reader, так и attr_writer, сохраняя еще одну строку кода.
Я думаю, что часть того, что смущает новых рубистов / программистов (как и я):
"Почему я не могу просто сказать экземпляру, что у него есть какой-либо атрибут (например, имя), и дать этому атрибуту значение одним махом?"
немного более обобщенный, но вот как он щелкнул для меня:
дано:
class Person
end
мы не определили человека как то, что может иметь имя или любые другие атрибуты, если на то пошло.
так если мы тут:
baby = Person.new
...и постарайся дать им имя...
baby.name = "Ruth"
получаем потому что в Rubyland класс объекта Person не является чем-то, что связано или способно иметь "имя" ... пока!
но мы можем использовать любой из предложенных методов (см. предыдущие ответы), как способ сказать, "экземпляр класса Person (baby
) теперь можно имеют атрибут под названием "имя", поэтому у нас есть не только синтаксический способ получения и установки этого имени, но для нас это имеет смысл."
опять же, ударяя по этому вопросу с немного другого и более общего угла, но я надеюсь, что это поможет следующему экземпляру класса, который найдет свой путь к этой теме.
если вы знакомы с концепцией ООП, вы должны ознакомиться с методом геттера и сеттера. attr_accessor делает то же самое в Ruby.
геттер и сеттер в общем порядке
class Person
def name
@name
end
def name=(str)
@name = str
end
end
person = Person.new
person.name = 'Eshaan'
person.name # => "Eshaan"
Сеттера
def name=(val)
@name = val
end
Геттер
def name
@name
end
метод геттера и сеттера в Ruby
class Person
attr_accessor :name
end
person = Person.new
person.name = "Eshaan"
person.name # => "Eshaan"
большинство приведенных выше ответов используют код. Это объяснение пытается ответить на него без использования какого-либо кода:
объяснение по аналогии
внешние стороны не могут получить доступ к внутренним секретам ЦРУ
давайте представим себе действительно секретное место: ЦРУ. Никто не знает, что происходит в ЦРУ, кроме людей внутри ЦРУ. Другими словами, внешние люди не могут получить доступ к какой-либо информации в ЦРУ. Но ведь нехорошо иметь организацию, которая полностью секретна, определенная информация предоставляется внешнему миру - только то, о чем ЦРУ хочет, чтобы все знали: например, директор ЦРУ, насколько экологически чистый этот отдел по сравнению со всеми другими правительственными ведомствами и т. д. Другая информация: например, кто является его тайными агентами в Ираке или Афганистане - эти типы вещей, вероятно, останутся секретом для следующих 150 годы.
Если вы находитесь вне ЦРУ, вы можете получить доступ только к информации, которую он сделал доступной для общественности. Или, используя жаргон ЦРУ, вы можете получить доступ только к информации, которая "очищена".
информация, которую ЦРУ хочет предоставить широкой общественности за пределами ЦРУ, называется:атрибуты.
значение чтения и записи атрибуты:
в случае ЦРУ большинство атрибутов "только для чтения". Это означает, если вы являетесь стороной внешний в ЦРУ, вы можете спрашиваю:не может делать с атрибутами "только для чтения" - это вносить изменения в изменения в ЦРУ. например, вы не можете сделать телефонный звонок и вдруг решить что вы хотите, чтобы Ким Кардашьян была Директор, или что вы хотите, чтобы Пэрис Хилтон была главнокомандующим.
-
Если атрибуты дали вам доступ "write", то вы можете внести изменения, если хотите, даже если вы были снаружи. В противном случае, единственное, что вы можете сделать, это прочитать.
другими словами, аксессоры позволяют вам делать запросы или вносить изменения в организации, которые в противном случае не допускают внешних людей, в зависимости от того, читаются или пишутся аксессоры средство доступа.
объекты внутри класса могут легко получить доступ друг к другу
- С другой стороны, если вы были уже внутриза пределами ЦРУ, вам просто не будет предоставлен доступ: вы не сможете узнать, кто они (читать access), и вы не сможете изменить свою миссию (write access).
то же самое с классами и вашей способностью получать доступ к переменным, свойствам и методам в них. НТН! Любые вопросы, пожалуйста, задайте, и я надеюсь, что смогу уточнить.
проще говоря, он определит сеттера и геттера для класса.
отметим, что
attr_reader :v is equivalant to
def v
@v
end
attr_writer :v is equivalant to
def v=(value)
@v=value
end
Так
attr_accessor :v which means
attr_reader :v; attr_writer :v
эквивалентны для определения сеттера и геттера для класса.
другой способ понять это-выяснить, какой код ошибки он устраняет, имея attr_accessor
.
пример:
class BankAccount
def initialize( account_owner )
@owner = account_owner
@balance = 0
end
def deposit( amount )
@balance = @balance + amount
end
def withdraw( amount )
@balance = @balance - amount
end
end
доступны следующие методы:
$ bankie = BankAccout.new("Iggy")
$ bankie
$ bankie.deposit(100)
$ bankie.withdraw(5)
следующие методы выдает ошибку:
$ bankie.owner #undefined method `owner'...
$ bankie.balance #undefined method `balance'...
owner
и balance
не, технически, метод, но атрибутом. Класс BankAccount не имеет def owner
и def balance
. Если это так, то вы можете использовать две команды ниже. Но этих двух методов не существует. Тем не менее, вы можете открыть атрибуты, как если бы вы открыть способ через attr_accessor
!! отсюда слово attr_accessor
. Атрибут. Средство доступа. Он обращается к атрибутам, как вы бы получить доступ к методу.
добавлять attr_accessor :balance, :owner
позволяет читать и писать balance
и owner
"метод". Теперь вы можете использовать последние 2 метода.
$ bankie.balance
$ bankie.owner
определяет именованный атрибут для этого модуля, где имя является символом.id2name, создание переменной экземпляра (@name) и соответствующий метод доступа для ее чтения. Также создает метод name= для установки атрибута.
module Mod
attr_accessor(:one, :two)
end
Mod.instance_methods.sort #=> [:one, :one=, :two, :two=]
чтобы суммировать атрибут accessor aka attr_accessor дает вам два бесплатных метода.
Как в Java они называют геттерами и сеттерами.
многие ответы показали хорошие примеры, поэтому я просто буду краток.
#the_attribute
и
#the_attribute=
в старых документах ruby хэш-тег # означает метод. Он также может включать префикс имени класса... Класса MyClass#заканчивается
атрибуты и методы-аксессоры
атрибуты-это компоненты класса, к которым можно получить доступ извне объекта. Они известны как свойства во многих других языках программирования. Их значения можно с помощью "точечной нотации", как в имя_объекта.имя атрибута. В отличие от 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 является экземпляром (объектом) класса автомобилей. Мы безуспешно пытались прочитать значение переменной экземпляра wheels извне объекта. Произошло то, что Ruby попытался вызвать метод с именем wheels в объекте c, но такой метод не был определен. Короче, имя_объекта.attribute_name пытается вызвать метод с именем attribute_name внутри объекта. Чтобы получить доступ к значению переменной wheels извне, нам нужно реализовать метод экземпляра с этим именем, который вернет значение этой переменной когда звонили. Это называется методом доступа. В общем контексте программирования обычным способом доступа к переменной экземпляра извне объекта является реализация методов доступа, также известных как методы getter и setter. Геттер позволяет считывать значение переменной, определенной внутри класса, извне, а сеттер позволяет записывать его извне.
в следующем примере мы добавили методы getter и setter в класс Car для доступа к колесам переменная извне объекта. Это не "рубиновый способ" определения геттеров и сеттеров; он служит только для иллюстрации того, что делают методы геттера и сеттера.
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
приведенный выше пример работает, и аналогичный код обычно используется для создания методов getter и setter на других языках. Однако 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
в приведенном выше примере атрибут wheels будет доступен для чтения и записи извне объекта. Если бы вместо attr_accessor мы использовали attr_reader, он был бы доступен только для чтения. Если бы мы использовали attr_writer, это было бы только для записи. Эти три метода сами по себе не являются геттерами и сеттерами, но при вызове они создают геттер и сеттер. методы сеттера для нас. Это методы, которые динамически (программно) генерируют другие методы; это называется метапрограммированием.
первый (более длинный) пример, который не использует встроенные методы Ruby, должен использоваться только тогда, когда требуется дополнительный код в методах getter и setter. Например, методу setter может потребоваться проверить данные или выполнить некоторые вычисления перед присвоением значения переменной экземпляра.
возможен доступ (чтение и запись) переменные экземпляра извне объекта с помощью встроенных методов instance_variable_get и instance_variable_set. Однако это редко оправданно и обычно плохая идея, поскольку обход инкапсуляции имеет тенденцию сеять всевозможные хаос.
Хммм. Много хороших ответов. Вот мои несколько центов.
attr_accessor
- Это простой метод, который помогает нам в уборке(высыхания) до повторятьgetter and setter
методы.чтобы мы могли больше сосредоточиться на написании бизнес-логики и не беспокоиться о сеттерах и геттерах.
основные возможности attr_accessor над другими является возможность доступа к данным из других файлов.
Таким образом, у вас обычно есть attr_reader или attr_writer, но хорошей новостью является то, что Ruby позволяет объединить эти два вместе с attr_accessor. Я думаю об этом как мой идти метод потому что он более хорошо округлен или универсален.
Кроме того, имейте в виду, что в Rails это устраняется, потому что он делает это для вас в задней части. Так другими словами: вам лучше использовать attr_acessor над двумя другими, потому что вам не нужно беспокоиться о том, чтобы быть конкретным, аксессор охватывает все это. Я знаю, что это скорее общее объяснение, но оно помогло мне как новичку.
надеюсь, что это помогло!