O que é o attr accessor em Ruby?

Estou a ter dificuldade em compreender em Ruby. Alguém me pode explicar isto?

 889
Author: codeforester, 2010-12-07

18 answers

Digamos que tens uma aula.
class Person
end

person = Person.new
person.name # => no method error
Obviamente, nunca definimos o método. Vamos fazer isso.
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

Aha, podemos ler o nome, mas isso não significa que podemos atribuir o nome. São dois métodos diferentes. O primeiro é chamado leitor e o segundo é chamado escritor . Ainda não criámos o escritor, por isso vamos fazer isso.

class Person
  def name
    @name
  end

  def name=(str)
    @name = str
  end
end

person = Person.new
person.name = 'Dennis'
person.name # => "Dennis"
Fantástico. Agora podemos escrever e ler a variável instância @name usando métodos de leitura e escrita. Excepto que isto é feito com tanta frequência, porquê perder tempo a escrever estes métodos todas as vezes? Podemos fazê-lo mais facilmente.
class Person
  attr_reader :name
  attr_writer :name
end
Até isto pode tornar-se repetitivo. Quando você quer tanto leitor e escritor basta usar acessor!
class Person
  attr_accessor :name
end

person = Person.new
person.name = "Dennis"
person.name # => "Dennis"

Funciona da mesma maneira! E adivinha: a variável de instância @name em nosso objeto pessoal será definida exatamente como quando fizemos manualmente, para que você possa usá-la em outros métodos.

class Person
  attr_accessor :name

  def greeting
    "Hello #{@name}"
  end
end

person = Person.new
person.name = "Dennis"
person.greeting # => "Hello Dennis"
É isso. Para entender como attr_reader, attr_writer, e attr_accessor métodos na verdade gerar métodos para você, ler outras respostas, livros, Ruby docs.
 2080
Author: Max Chernyak, 2017-02-10 21:28:46

O acessor é apenas um método . (O link deve fornecer mais informações sobre como ele funciona - veja os pares de métodos gerados, e um tutorial deve mostrar-lhe como usá-lo.)

O truque é que class é não é uma definição em Ruby (é "apenas uma definição" em linguagens como C++ e Java), mas é um expressão que avalia. É durante esta avaliação que o método attr_accessor é invocado que, por sua vez, modifica a classe actual-lembre-se do receptor implícito: self.attr_accessor, onde self é o objecto de classe "aberto" neste ponto.

A necessidade de attr_accessor e amigos, é, bem:

  1. O Ruby, como o Smalltalk, não permite que variáveis de instância sejam acessadas fora dos métodos1 por esse objecto. Ou seja, variáveis de instância não podem ser acessadas na forma x.y Como é comum em say, Java ou mesmo Python. Em Ruby y é sempre tomada como uma mensagem a enviar (ou "método a chamar"). Assim os métodos attr_* criam invólucros que proxy o acesso à instância @variable através de métodos criados dinamicamente.

  2. O Boilerplate é uma treta.

Espero que isto esclareça alguns dos pequenos detalhes. Feliz código.

1 isto não é estritamente verdade e existem algumas "técnicas" em torno deste , mas não há suporte de sintaxe para o acesso de" instância pública variável".

 115
Author: Community, 2017-05-23 12:02:48

attr_accessor é (como @pst afirmou) apenas um método. O que ele faz é criar mais métodos para você.

Então este código aqui:

class Foo
  attr_accessor :bar
end

É equivalente a este código:

class Foo
  def bar
    @bar
  end
  def bar=( new_value )
    @bar = new_value
  end
end
Podes escrever este tipo de método em 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
 63
Author: Phrogz, 2010-12-06 21:29:34

attr_accessor é muito simples:

attr_accessor :foo

É um atalho para:

def foo=(val)
  @foo = val
end

def foo
  @foo
end

Não é nada mais do que um getter / setter para um objecto

 35
Author: efalcao, 2010-12-06 21:28:47
Basicamente, falsificam atributos de dados acessíveis ao público, que a Ruby não tem.
 17
Author: Tyler Eaves, 2010-12-06 21:11:11

É apenas um método que define os métodos de getter e setter por exemplo variáveis. Um exemplo de implementação seria:

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
 17
Author: Chuck, 2010-12-06 21:29:29
Também enfrentei este problema e escrevi uma resposta um pouco longa a esta pergunta. Já existem algumas grandes respostas a este respeito, mas quem quiser mais esclarecimentos, espero que a minha resposta possa ajudar.

Inicializar O Método

Inicializar permite-lhe definir os dados para uma instância de um objecto após a criação da instância, em vez de ter de Os definir numa linha separada no seu código cada vez que cria uma nova instância da classe.

class Person
  attr_accessor :name

  def initialize(name)
    @name = name
  end


  def greeting
    "Hello #{@name}"
  end
end

person = Person.new("Denis")
puts person.greeting
No código acima estamos definir o nome "Denis" usando o método inicializar, passando Dennis através do parâmetro in inicialize. Se quiséssemos definir o nome sem o método de inicialização poderíamos fazê-lo assim:
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
No código acima, definimos o nome usando o método de identificação do utilizador. person.name, ao invés de definir os valores após a inicialização do objeto.

Ambos os "métodos" de fazer este trabalho, mas a inicialização poupa-nos tempo e linhas de código.

Este é o ... é o único trabalho de inicialização. Você não pode invocar inicializar como um método. Para obter efectivamente os valores de um objecto de instância, é necessário utilizar os seus assinantes e os seus assinantes ("attr_reader", "attr_writer" ("set") e "attr_acessor" ("ambos"). Veja abaixo para mais detalhes sobre estes.

Getters, Setters (attr_reader, attr_writer, attr_accessor)

([8]) locutor: o objectivo de um locutor é devolver o valor de uma dada variável de instância. Visite o código de amostra abaixo para obter uma discriminação sobre isso.
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

No código acima, você está chamando os métodos "item_name" e "quantidade" na instância do Item "exemplo". O " põe exemplo.item_name " e " example.quantidade "irá retornar (ou" obter") o valor para os parâmetros que foram passados para o" exemplo " e exibi-los para a tela.

Felizmente, em Ruby existe um método inerente que nos permite escrever este código de forma mais sucinta: o método de leitura rápida. Ver o código abaixo;
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

Esta sintaxe funciona exactamente como da mesma forma, só que nos poupa seis linhas de código. Imagine se você tivesse mais 5 estado atribuível à classe de itens? O código demoraria muito rapidamente.

O que me passou pela cabeça com métodos de montagem é que, aos meus olhos, parecia desempenhar uma função idêntica ao método de inicialização. Abaixo eu explico a diferença com base no meu entendimento;

Como indicado anteriormente, o método inicializar permite-lhe definir os valores para uma instância de um objecto sobre um objecto criacao.

Mas e se você quiser definir os valores mais tarde, depois que a instância foi criada, ou alterá-los depois que eles foram inicializados? Este seria um cenário onde você usaria um método setter. ESSA É A DIFERENÇA. Você não tem que "definir" um estado em particular quando você está usando o método attr_writer inicialmente.

O código abaixo é um exemplo de usar um método de setter para declarar o valor item_ nome para esta instância da classe de itens. Note - se que continuamos a use o método getter attr_reader para que possamos obter os valores e imprimi-los para a tela, no caso de você quiser testar o código por conta própria.

class Item

attr_reader :item_name

  def item_name=(str)
    @item_name = (str)
  end

end
O código que se segue é um exemplo de Utilização da Seguradora para encurtar mais uma vez o nosso código e poupar-nos tempo.
class Item

attr_reader :item_name
attr_writer :item_name

end

item = Item.new
puts item.item_name = "TV"

O código abaixo é uma reiteração do exemplo inicializar acima de onde estamos usando inicialize para definir o valor dos objetos do item_ nome após a criação.

class Item

attr_reader :item_name

  def initialize(item_name)
    @item_name = item_name
  end

end

item = Item.new("TV")
puts item.item_name
Serviço das Publicações Oficiais das Comunidades Europeias ladrão e segurador, poupando-lhe mais uma linha de código.
 12
Author: Jbur43, 2016-05-05 00:12:45
Acho que parte do que confunde novos Rubistas / programadores (como eu) é:

"Por que não posso dizer à instância que ela tem algum atributo dado (por exemplo, nome) e dar a esse atributo um valor tudo de uma só vez?"

Um pouco mais generalizado, mas foi assim que me pareceu:

Indicado:

class Person
end

Ainda não definimos a pessoa como algo que pode ter um nome ou qualquer outro atributo para isso.

Então, se nós ...
baby = Person.new

...e tenta dar-lhes um nome...

baby.name = "Ruth"

Temos um erro porque, no Rubyland, uma classe de pessoa de objeto não é algo que esteja associado ou seja capaz de ter um "nome" ... ainda!

, MAS podemos usar qualquer uma das dada métodos (vide respostas anteriores) como uma forma de dizer, "Uma instância de uma classe Pessoa (baby) pode agora tem um atributo chamado "nome", portanto, não temos apenas um sintática forma de obtenção e definição de nome, mas ele faz sentido para a gente fazer entao."

Mais uma vez, fazendo esta pergunta de um ângulo um pouco diferente e mais geral, mas espero que isto ajude a próxima instância da pessoa de classe que encontra o seu caminho para este tópico.
 10
Author: Ben, 2014-09-26 01:24:36

Se está familiarizado com o conceito de OOP, deve estar familiarizado com o método getter e setter. o acessor faz o mesmo em Ruby.

Getter e Setter em geral

class Person
  def name
    @name
  end

  def name=(str)
    @name = str
  end
end

person = Person.new
person.name = 'Eshaan'
person.name # => "Eshaan"

Método De Configuração

def name=(val)
  @name = val
end

Método Getter

def name
  @name
end

Método Getter e Setter em Ruby

class Person
  attr_accessor :name
end

person = Person.new
person.name = "Eshaan"
person.name # => "Eshaan"
 10
Author: Ahmed Eshaan, 2016-08-04 14:59:39

A maioria das respostas acima usam código. Esta explicação tenta responder sem usar qualquer código:

Explicação por analogia

Partes externas não podem aceder a segredos internos da CIA.

  • Vamos imaginar um lugar realmente secreto: a CIA. Ninguém sabe o que está a acontecer na CIA, além das pessoas dentro da CIA. Por outras palavras, as pessoas externas não podem aceder a qualquer informação na CIA. Mas porque não é bom ter uma organização isso é completamente secreto, certas informações são disponibilizadas ao mundo exterior - apenas coisas que a CIA quer que todos saibam, é claro: por exemplo, o diretor da CIA, como este departamento é amigo do ambiente em comparação com todos os outros departamentos do governo, etc. Outras informações: por exemplo, quem são os seus agentes secretos no Iraque ou no Afeganistão - este tipo de coisas provavelmente permanecerá um segredo para os próximos 150 anos.

  • Se você está fora da CIA você só pode acesse as informações que disponibilizou ao público. Ou para usar a linguagem da CIA, só se pode aceder a informações "limpas".

  • As informações que a CIA quer disponibilizar ao público em geral fora da CIA são chamadas: Atributos.

O significado dos atributos de leitura e escrita:

  • No caso da CIA, a maioria dos atributos são "apenas para leitura". Isto significa que se for uma parte a CIA, podes perguntar: quem é o director da CIA?"e terás uma resposta directa. Mas o que você não pode fazer com atributos "só de leitura" é fazer mudanças na CIA. por exemplo, não se pode fazer um telefonema e, de repente, decidir que quer que Kim Kardashian seja o Director, ou que quer que Paris Hilton seja o Comandante Supremo.

  • Se os atributos lhe deram acesso de "escrita" , então você pode fazer alterações se quiser, mesmo que você estávamos lá fora. Caso contrário, a única coisa que podes fazer é ler.

    Por outras palavras, os acessores permitem-lhe fazer perguntas, ou fazer alterações, a organizações que, de outro modo, não deixam entrar pessoas externas, dependendo se os acessores são lidos ou escrevem acessores.

Objetos dentro de uma classe podem facilmente acessar uns aos outros

    Por outro lado, se já estivesse dentro da CIA, podia facilmente ligar para o seu agente da CIA. Kabul e pergunta-lhe se quer beber uma cerveja com o Informador de Kabul depois do trabalho. Mas se você estiver fora da CIA, você simplesmente não terá acesso: você não será capaz de saber quem eles são (acesso de leitura), e você não será capaz de mudar sua missão (acesso de escrita).

Exactamente a mesma coisa com as classes e a sua capacidade de aceder a variáveis, propriedades e métodos dentro delas. HTH! Qualquer pergunta, por favor, faça e espero poder esclarecer.

 10
Author: BKSpurgeon, 2018-04-15 13:56:04

Simplificando, irá definir um setter e getter para a classe.

Note que

attr_reader :v is equivalant to 
def v
  @v
end

attr_writer :v is equivalant to
def v=(value)
  @v=value
end

Por isso

attr_accessor :v which means 
attr_reader :v; attr_writer :v 

São equivalentes para definir um setter e getter para a classe.

 7
Author: Marcus Thornton, 2014-08-12 08:30:42

Simplesmente attr-accessor cria os métodos getter e setter para os atributos indicados

 5
Author: Veeru, 2014-03-17 11:05:49

Outra maneira de entender é descobrir que código de erro elimina tendo attr_accessor.

Exemplo:

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

Estão disponíveis os seguintes métodos:

$ bankie = BankAccout.new("Iggy")
$ bankie 
$ bankie.deposit(100)
$ bankie.withdraw(5)

Os seguintes métodos lançam erros:

$ bankie.owner     #undefined method `owner'... 
$ bankie.balance   #undefined method `balance'...

owner e balance não são, tecnicamente, um método, mas um atributo. A classe BankAccount não tem def owner e def balance. Se isso acontecer, então você pode usar os dois comandos abaixo. Mas esses dois métodos não existem. No entanto, você pode access atributos como se tivesses access um método via attr_accessor!! daí a palavra attr_accessor. Atributo. Descritor. Ele acede a atributos como você teria acesso a um método.

Adicionar attr_accessor :balance, :owner permite-lhe ler e escrever balance e owner "método". Agora você pode usar os últimos dois métodos.

$ bankie.balance
$ bankie.owner
 4
Author: Iggy, 2016-09-13 18:26:41

Define um atributo nomeado para este módulo, onde o nome é symbol.id2name, criando uma variável de instância (@name) e um método de acesso correspondente para o ler. Também cria um método chamado NOME= para definir o atributo.

module Mod
  attr_accessor(:one, :two)
end
Mod.instance_methods.sort   #=> [:one, :one=, :two, :two=]
 2
Author: Praveen_Shukla, 2015-08-11 16:12:37
Para resumir um acessor de atributos, conhecido por "attr_acessor", dá-lhe dois métodos gratuitos. Como em Java chamam-se getters e setters.

Muitas respostas mostraram bons exemplos, por isso vou ser breve.

#the_ attribute

E

#the_ attribute=

No antigo ruby docs uma etiqueta de hash # significa um método. Ele também pode incluir um prefixo de nome de classe... MyClass # my_method

 1
Author: Douglas G. Allen, 2016-11-14 03:56:47

Atributos e métodos de acesso

Os atributos são componentes de classe que podem ser acedidos fora do objecto. Eles são conhecidos como propriedades em muitas outras linguagens de programação. Seus valores são acessíveis usando a "notação dot", como no object_name.nome de atribuição. Ao contrário de Python e algumas outras linguagens, Ruby não permite que variáveis de instância sejam acessadas diretamente de fora do objeto.

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>

No exemplo acima, c é uma instância (objeto) do carro classe. Nós tentamos sem sucesso ler o valor da variável de instância de rodas de fora do objeto. O que aconteceu foi que Ruby tentou chamar um método chamado rodas dentro do objeto c, mas nenhum desses métodos foi definido. Resumindo, nome do objecto.o attribute_name tenta chamar um método chamado attribute_name dentro do objeto. Para acessar o valor da variável rodas a partir do exterior, precisamos implementar um método de instância por esse nome, que irá devolver o valor dessa variável quando chamado. Chama-se Método de acesso. No contexto de programação geral, a maneira usual de acessar uma variável de instância de fora do objeto é implementar métodos de accessor, também conhecidos como métodos getter e setter. Um getter permite que o valor de uma variável definida dentro de uma classe seja lido do lado de fora e um setter permite que seja escrito do lado de fora.

No seguinte exemplo, adicionámos métodos de getter e setter à classe de carros para aceder à variável de rodas a partir do exterior. objecto. Esta não é a" maneira Ruby " de definir getters e setters; ela serve apenas para ilustrar o que getter e setter métodos fazem.

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

O exemplo acima funciona e um código similar é comumente usado para criar métodos getter e setter em outras línguas. No entanto, a Ruby oferece uma forma mais simples de o fazer: três métodos incorporados, denominados "extra-terrestre", "extra-terrestre" e "extra-terrestre". O método attr_reader torna uma instância legível por terceiros, tornando-a escriturável, e o acessor torna-o legível e gravável.

O exemplo acima pode ser reescrito assim.

class Car
  attr_accessor :wheels
end

f = Car.new
f.wheels = 4
f.wheels  # Output: => 4

No exemplo acima, o atributo wheels será legível e gravável de fora do objeto. Se em vez de um acessor, usássemos um leitor, seria apenas para leitura. Se usássemos um segurador, seria apenas para escrever. Esses três métodos não são getters e setters em si mesmos, mas, quando chamados, eles criam getter e setter métodos para nós. São métodos que dynamically (programmatically) generate other methods; that's called metaprogramming.

O primeiro exemplo (mais longo), que não emprega os métodos embutidos da Ruby, só deve ser usado quando for necessário um código adicional nos métodos getter e setter. Por exemplo, um método de setter pode precisar validar dados ou fazer algum cálculo antes de atribuir um valor a uma variável de instância.

É possível aceder (ler e escrever) variáveis de instância de fora do objecto, usando o instance_variable_get e instance_ variable_ set embutidos. No entanto, isso raramente é justificável e geralmente uma má ideia, já que contornar encapsulação tende a causar todo tipo de caos.

 0
Author: BrunoFacca, 2016-07-05 11:41:58

Hmmm. Muitas boas respostas. Aqui estão os meus poucos cêntimos.

  • attr_accessor é um método simples que nos ajuda a limpar [[[8]}a seco ] até à repetição getter and setter métodos.

  • Para que possamos nos concentrar mais em escrever lógica de negócios e não nos preocupar com os setters e getters.

 -1
Author: Abibullah Rahamathulah, 2017-08-29 09:50:08
{[1] a funcionalidade principal do acessor em relação aos outros é a capacidade de aceder a dados de outros ficheiros.
Por isso, normalmente terias um ladrão ou um escritor, mas a boa notícia é que a Ruby te deixa combinar estes dois com um acessor. Eu penso nisso como o meu método de ir porque é mais bem arredondado ou versátil. Além disso, peep em mente que em trilhos, isso é eliminado porque ele faz isso para você na parte de trás. Por outras palavras,: é melhor usares um acessor em vez dos outros dois, porque não tens de te preocupar em ser específico, o acessor cobre tudo. Sei que é mais uma explicação geral, mas ajudou-me como principiante. Espero que isto ajude!
 -3
Author: creativegeek, 2016-06-17 15:40:55