Ruby 中的 attr_accessor 是什么?

我很难理解 Ruby 中的attr_accessor 。谁可以给我解释一下这个?

答案

class Person
end

person = Person.new
person.name # => no method error
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"
class Person
  attr_reader :name
  attr_writer :name
end
class Person
  attr_accessor :name
end

person = Person.new
person.name = "Dennis"
person.name # => "Dennis"
class Person
  attr_accessor :name

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

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

attr_accessor 只是一种方法 。 (该链接应提供有关其工作原理的更多见解 - 查看生成的方法对,并且一个教程应向您展示如何使用它。)

诀窍是, class 不是 Ruby 中的定义 (在诸如 C ++ 和 Java 之类的语言中 “只是定义”),而是一个可求值表达式 。正是在此评估期间,调用attr_accessor方法会依次修改当前类 - 记住隐式接收者: self.attr_accessor ,其中self是此时的 “开放” 类对象。

attr_accessor和朋友的需求很好:

  1. 像 Smalltalk 一样,Ruby 不允许在该对象的方法1之外访问实例变量。也就是说,实例变量不能以xy形式访问,就像 Java 甚至 Python 一样。在 Ruby 中, y始终被视为要发送的消息(或 “调用方法”)。因此, attr_*方法创建包装器,该包装器通过动态创建的方法代理实例@variable访问。

  2. 样板糟透了

希望这可以澄清一些小细节。快乐的编码。


1这并非完全正确, 围绕此一些 “技巧” ,但是不支持 “公共实例变量” 访问的语法。

attr_accessor只是一个方法(如 @pst 所述)。它的作用是为您创建更多方法。

所以这里的代码:

class Foo
  attr_accessor :bar
end
class Foo
  def bar
    @bar
  end
  def bar=( new_value )
    @bar = new_value
  end
end
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

它只不过是对象的获取器 / 设置器

基本上,它们伪造了可公开访问的数据属性,而 Ruby 没有。

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

无需任何代码的简单说明

上面的大多数答案都使用代码。这个解释试图通过类比 / 故事不使用任何答案来回答它:

外部团体无法访问 CIA 内部机密

  • 让我们想象一个真正秘密的地方:中央情报局。除了中央情报局内部的人员,没人知道中央情报局正在发生什么。换句话说,外部人员无法访问 CIA 中的任何信息。但是因为拥有一个完全秘密的组织并没有什么好处,所以某些信息会公开给外界 - 当然只有 CIA 希望所有人都知道的事情:例如 CIA 的局长,比较该部门对环境的友好程度其他信息:例如谁是伊拉克或阿富汗的秘密特工 - 这些事情在未来 150 年内可能仍然是秘密。

  • 如果您不在中央情报局范围内,则只能访问它向公众公开的信息。或者,要使用 CIA 的说法,您只能访问 “已清除” 的信息。

  • CIA 希望向 CIA 之外的公众公开的信息称为: 属性。

读写属性的含义:

  • 对于 CIA,大多数属性是 “只读” 的。这意味着,如果你是外部 CIA 的一方,你可以问:“谁是中情局的局长?” 您会得到一个直接的答案。但是,使用 “只读” 属性不能做的是在 CIA 中进行更改更改。例如,您无法打个电话,突然决定让金 · 卡戴珊(Kim Kardashian)担任导演,或者让帕里斯 · 希尔顿(Paris Hilton)担任总司令。

  • 如果这些属性为您提供 “写” 访问权限,那么即使您不在,也可以进行更改。否则,您唯一可以做的就是阅读。

    换句话说,访问者允许您对访问组织是外部访问者的组织进行查询或更改,具体取决于访问者是读取访问者还是写入访问者。

类内的对象可以轻松地相互访问

  • 另一方面,如果您已经 CIA 内部 ,则可以轻松地致电喀布尔的 CIA 特工,因为如果您已经在内部 ,则可以轻松访问此信息。但是,如果您不在 CIA 范围内,则根本不会获得访问权限:您将无法知道他们是谁(读访问权限),也将无法更改他们的任务(写访问权限)。

类与您访问类中的变量,属性和方法的能力完全相同。 HTH!任何问题,请问,希望我能澄清。

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
class Person
  attr_accessor :name
end

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

  def initialize(name)
    @name = name
  end


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

person = Person.new("Denis")
puts person.greeting
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
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
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
class Item

attr_reader :item_name

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

end
class Item

attr_reader :item_name
attr_writer :item_name

end

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

attr_reader :item_name

  def initialize(item_name)
    @item_name = item_name
  end

end

item = Item.new("TV")
puts item.item_name
class Person
end
baby = Person.new
baby.name = "Ruth"