это - ruby attr_reader




Что такое attr_accessor в Ruby? (12)

Атрибуты и методы доступа

Атрибуты - это компоненты класса, к которым можно получить доступ извне объекта. Они известны как свойства во многих других языках программирования. Их значения доступны с использованием «точечной нотации», как в 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, но такой метод не был определен. Короче говоря, object_name.attribute_name пытается вызвать метод с именем attribute_name внутри объекта. Чтобы получить доступ к значению переменной колеса снаружи, нам нужно реализовать метод экземпляра с помощью этого имени, которое будет возвращать значение этой переменной при вызове. Это называется методом доступа. В общем контексте программирования обычным способом доступа к переменной экземпляра извне объекта является реализация методов доступа, также известных как методы getter и setter. Геттер позволяет считывать значение переменной, определенной внутри класса, снаружи, а сеттер позволяет записывать ее извне.

В следующем примере мы добавили методы getter и setter в класс Car для доступа к переменной колес извне объекта. Это не «рубиновый путь» определения геттеров и сеттеров; он служит только для иллюстрации того, какие методы getter и setter делают.

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

В приведенном выше примере атрибут колес будет доступен для чтения и записи извне объекта. Если вместо attr_accessor мы использовали attr_reader, он был бы доступен только для чтения. Если бы мы использовали attr_writer, это было бы только для записи. Эти три метода не являются геттерами и сеттерами сами по себе, но, когда они называются, они создают методы получения и настройки для нас. Это методы, которые динамически (программно) генерируют другие методы; это называется метапрограммированием.

Первый (более длинный) пример, который не использует встроенные методы Ruby, должен использоваться только тогда, когда требуется дополнительный код в методах getter и setter. Например, для метода установки может потребоваться проверка данных или выполнение некоторых вычислений до назначения значения переменной экземпляра.

Можно получить доступ (чтение и запись) переменных экземпляра вне объекта, используя встроенные методы instance_variable_get и instance_variable_set. Однако это редко бывает оправданным и обычно плохая идея, поскольку обход инкапсуляции имеет тенденцию приводить к разным хаосам.

Мне трудно понять attr_accessor в Ruby. Может кто-то объяснить это мне?


В большинстве приведенных ответов используется код. Это объяснение пытается ответить на него без использования какого-либо кода:

Объяснение по аналогии

Внешние стороны не могут получить доступ к секретам ЦРУ

  • Представим себе действительно секретное место: ЦРУ. Никто не знает, что происходит в ЦРУ, кроме людей внутри ЦРУ. Другими словами, внешние лица не могут получить доступ к какой-либо информации в ЦРУ. Но поскольку нет ничего хорошего в организации, которая полностью секретна, определенная информация предоставляется внешнему миру - только то, что ЦРУ хочет, чтобы все знали о нем, конечно: например, директор ЦРУ, насколько экологичен этот отдел для всех других правительственных ведомств и т. д. Другая информация: например, кто является ее тайными оперативниками в Ираке или Афганистане, эти типы вещей, вероятно, останутся тайной в течение следующих 150 лет.

  • Если вы находитесь за пределами ЦРУ, вы можете получить доступ к информации, доступной только для общественности. Или использовать язык ЦРУ, вы можете получить доступ только к информации, которая «очищена».

  • Информация, которую ЦРУ хочет предоставить широкой публике вне ЦРУ, называется: атрибутами.

Значение атрибутов чтения и записи:

  • В случае ЦРУ большинство атрибутов являются «только для чтения». Это означает, что если вы являетесь сторонником ЦРУ, вы можете спросить: «Кто является директором ЦРУ?» и вы получите прямой ответ. Но то, что вы не можете сделать с атрибутами «только для чтения», - это внести изменения в ЦРУ. например, вы не можете позвонить и вдруг решите, что вы хотите, чтобы Ким Кардашян был директором, или что вы хотите, чтобы Пэрис Хилтон был главнокомандующим.

  • Если атрибуты дали вам доступ «запись», вы можете внести изменения, если хотите, даже если вы были на улице. В противном случае, вы можете прочитать только одно.

    Другими словами, аксессоры позволяют вам делать запросы или вносить изменения в организации, которые в противном случае не разрешают внешним пользователям, в зависимости от того, читают ли аксессоры или ищут записи.

Объекты внутри класса могут легко обращаться друг к другу

  • С другой стороны, если вы уже были в ЦРУ, тогда вы можете легко вызвать своего оперативника ЦРУ в Кабуле и спросить его, хочет ли он после питья пиво с местным информатором Кабула. Но если вы находитесь за пределами ЦРУ, вам просто не будет предоставлен доступ: вы не сможете узнать, кто они (доступ для чтения), и вы не сможете изменить свою миссию (доступ на запись).

Точная вещь с классами и возможность доступа к переменным, свойствам и методам внутри них. НТН! Любые вопросы, пожалуйста, спросите, и я надеюсь, что смогу уточнить.


Допустим, у вас есть класс 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

Даже это может повториться. Когда вы хотите, чтобы и читатель, и писатель просто использовали аксессуар!

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 действительно генерируют методы для вас, читайте другие ответы, книги, рубиновые документы.


Другой способ понять это - выяснить, какой код ошибки он устраняет, используя 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 . Атрибут. 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=]

Основная функция attr_accessor над другими - это возможность доступа к данным из других файлов.
Таким образом, вы обычно будете иметь attr_reader или attr_writer, но хорошей новостью является то, что Ruby позволяет объединить эти два вместе с attr_accessor. Я думаю, что это мой метод, потому что он более округлый или универсальный. Кроме того, обратите внимание, что в Rails это устраняется, потому что это делает это для вас в задней части. Итак, другими словами: вам лучше использовать attr_acessor над двумя другими, потому что вам не нужно беспокоиться о том, чтобы быть конкретным, аксессуар покрывает все это. Я знаю, что это скорее общее объяснение, но оно помогло мне в качестве новичка.

Надеюсь, это помогло!


Проще говоря, это определит сеттер и getter для класса.

Обратите внимание, что

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 - это простой метод, который помогает нам в очистке ( СУШЕСТВИИ ) повторять методы получения и настройки.

  • Чтобы мы могли больше сосредоточиться на написании бизнес-логики и не беспокоиться о сеттерах и геттерах.


Это всего лишь метод, который определяет методы 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

Я думаю, что часть того, что смущает новых рубистов / программистов (например, я):

«Почему я не могу просто указать экземпляру, что у него есть какой-либо атрибут (например, имя), и дать этому атрибуту значение всего одним махом?»

Немного более обобщен, но вот как он щелкнул меня:

Дано:

class Person
end

Мы не определили Person как нечто, что может иметь имя или любые другие атрибуты.

Итак, если мы тогда:

baby = Person.new

... и попробуйте дать им имя ...

baby.name = "Ruth"

Мы получаем ошибку, потому что в Rubyland класс объекта Person не является тем, что связано или может иметь «имя» ... еще!

НО мы можем использовать любой из этих методов (см. Предыдущие ответы) в качестве способа сказать: «У экземпляра класса Person ( baby ) теперь может быть атрибут« имя », поэтому у нас есть не только синтаксический способ получения и назначить это имя, но для нас это имеет смысл ».

Опять же, ударив этот вопрос из немного другого и более общего угла, но я надеюсь, что это поможет следующему экземпляру класса Person, который находит свой путь к этой теме.


attr_accessor - это всего лишь метод . (Ссылка должна дать больше информации о том, как она работает - посмотрите на пары генерируемых методов, а в учебнике должно быть показано, как ее использовать).

Трюк в том, что class не является определением в Ruby (это «просто определение» в таких языках, как C ++ и Java), но это выражение, которое оценивается . Именно во время этой оценки, когда attr_accessor метод attr_accessor который, в свою очередь, изменяет текущий класс - помните неявный получатель: self.attr_accessor , где self - это «открытый» объект класса в данный момент.

Необходимость attr_accessor и друзей - это хорошо:

  1. Ruby, подобно Smalltalk, не позволяет обращаться к переменным экземпляра вне методов 1 для этого объекта. То есть, переменные экземпляра невозможно получить в форме xy как это принято в Java, или даже Python. В Ruby y всегда используется как сообщение для отправки (или «метод для вызова»). Таким образом, методы attr_* создают оболочки, которые проксируют доступ к экземпляру @variable через динамически созданные методы.

  2. Бойлер

Надеюсь, это прояснит некоторые детали. Счастливое кодирование.

1 Это не совсем верно, и вокруг этого есть некоторые «методы» , но нет поддержки синтаксиса для доступа «public instance variable».


attr_accessor очень прост:

attr_accessor :foo

это ярлык для:

def foo=(val)
  @foo = val
end

def foo
  @foo
end

это не что иное, как геттер / сеттер для объекта







ruby