Ruby中的attr_accessor是什么?

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

假设你有一个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 

啊哈,我们可以读取这个名字,但是这并不意味着我们可以分配这个名字。 这是两种不同的方法。 前者被称为读者 ,后者被称为作家 。 我们还没有创build作家,所以让我们这样做。

 class Person def name @name end def name=(str) @name = str end end person = Person.new person.name = 'Dennis' person.name # => "Dennis" 

真棒。 现在我们可以使用读写器方法来编写和读取实例variables@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" 

以同样的方式工作! 并猜测:我们person对象中的实例variables@name将被设置为就像我们手动执行的那样,所以您可以在其他方法中使用它。

 class Person attr_accessor :name def greeting "Hello #{@name}" end end person = Person.new person.name = "Dennis" person.greeting # => "Hello Dennis" 

而已。 为了理解attr_readerattr_writerattr_accessor方法如何为您生成方法,请阅读其他答案,书籍和ruby文档。

attr_accessor 只是一个方法 。 (该链接应该提供更多关于它如何工作的信息 – 查看生成的方法对,并且教程应该告诉你如何使用它。)

诀窍是这个class 不是 Ruby中的定义 (它在C ++和Java等语言中只是一个定义),但是它是一个expression式 。 正是在这个评估过程中,调用了attr_accessor方法,这个方法又修改了当前的类 – 记住隐式的接收者: self.attr_accessorself在这里是“open”类对象。

attr_accessor和朋友的需求,是:

  1. Ruby和Smalltalk一样,不允许在对象的方法1之外访问实例variables。 也就是说,实例variables不能以xyforms访问,就像在Java或甚至Python中常见的那样。 在Ruby中, y总是作为一个消息发送(或“调用方法”)。 因此, attr_*方法通过dynamic创build的方法创build代理实例@variable访问的包装器。

  2. 锅板吮吸

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


1这并非严格意义上的,这里有一些“技巧” ,但是没有对“公共实例variables”访问的语法支持。

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

这只是一个为实例variables定义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 

基本上他们伪造了公共可访问的数据属性,这是Ruby不具备的。

我认为混淆新的Ruby /程序员(像我自己)的一部分是:

“为什么我不能告诉实例它有任何给定的属性(例如,名称),并给这个属性一个值,一举一动?

有点更一般化,但这是它为我点击:

鉴于:

 class Person end 

我们还没有将Person定义为可以具有某个名称或任何其他属性的事物。

那么如果我们那么:

 baby = Person.new 

…并试图给他们一个名字…

 baby.name = "Ruth" 

我们得到一个错误,因为在Rubyland中,一个Person类的对象不是与某个“名字”相关联或者能够拥有一个“名字”的东西。

但是我们可以使用任何给定的方法(参见之前的答案)来说:“一个Person类的实例( baby现在可以拥有一个名为'name'的属性,因此我们不仅具有语法并设定这个名字,但这样做对我们来说是有道理的。“

再一次,从一个稍微不同的,更一般的angular度来看这个问题,但是我希望这有助于下一个Person类的下一个实例,他find了这个线程。

如果你熟悉OOP概念,你必须熟悉getter和setter方法。 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" 

Setter方法

 def name=(val) @name = val end 

Getter方法

 def name @name end 

Ruby中的Getter和Setter方法

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

我也遇到了这个问题,写了一个比较冗长的答案。 已经有一些很好的答案了,但是有人想要更多的澄清,我希望我的答案能够帮助

初始化方法

初始化允许您在创build实例时将数据设置为对象的实例,而不必在每次创build类的新实例时将其设置在代码中的单独一行中。

 class Person attr_accessor :name def initialize(name) @name = name end def greeting "Hello #{@name}" end end person = Person.new("Denis") puts person.greeting 

在上面的代码中,我们使用initialize方法通过在Initialize中传递Dennis参数来设置名称“Denis”。 如果我们想在不使用初始化方法的情况下设置名称,我们可以这样做:

 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 

在上面的代码中,我们使用person.name调用attr_accessor setter方法来设置名称,而不是在初始化对象时设置值。

这两个“方法”的工作,但初始化为我们节省了时间和代码行。

这是初始化的唯一工作。 你不能调用初始化方法。 要实际获取实例对象的值,需要使用getter和setter(attr_reader(get),attr_writer(set)和attr_accessor(both))。 请参阅下面的更多细节。

Getters,Setters(attr_reader,attr_writer,attr_accessor)

Getters,attr_reader:getter的全部目的是返回特定实例variables的值。 请访问下面的示例代码,了解这方面的细节。

 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 

在上面的代码中,您正在项目“example”的实例上调用方法“item_name”和“quantity”。 “puts example.item_name”和“example.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 

这个语法的工作方式完全相同,只是它为我们节省了六行代码。 试想一下,如果你有五个更多的国家可归于物品类? 代码会很快变长。

Setter,attr_writer:最初用setter方法交叉我的是,在我看来,它似乎执行与初始化方法相同的function。 下面我根据我的理解来解释这个区别。

如前所述,initialize方法允许您在创build对象时设置对象实例的值。

但是如果你希望在创build实例之后设置值,或者在初始化后更改它们呢? 这将是一个你会使用setter方法的场景。 这是不同的。 当您最初使用attr_writer方法时,不必“设置”特定的状态。

下面的代码是使用setter方法为Item类的这个实例声明值item_name的示例。 请注意,我们继续使用getter方法attr_reader,以便我们可以获取值并将其打印到屏幕上,以防万一您想自行testing代码。

 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" 

下面的代码是我们在创build时使用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的函数,为你节省一行代码。

大多数上面的答案使用代码。 我没有重复他们说的话,所以我会尝试解释没有代码的概念

说明

外部党派不能访问中央情报局的内部秘密

  • 让我们想象一个非常秘密的地方。 一个机构。 我们把这个机构叫做中央情报局。 除了中央情报局的人员之外,没有人知道中央情报局正在发生什么事情。 换句话说,外部人不能访问中央情报局的任何信息。 但是因为拥有一个完全秘密的组织是不好的,所以有一些信息可以提供给外部世界 – 只有中情局当然希望每个人都知道的东西:例如中情局局长,这个部门比较环保所有其他的政府部门等。其他信息:例如,谁是在伊拉克或阿富汗的秘密行动者 – 这些types的事情可能在未来150年保持秘密。

  • 你只能访问中央情报局向公众提供的信息(如果你是Joe Bloggs的话)。 或者使用中情局的说法,你只能访问被“清除”的信息。

    中央情报局希望提供给中央情报局以外的公众的信息称为: 属性。

读写属性的含义:

  • 在CIA的情况下,大多数属性是“只读”的。 这意味着你可以问: “谁是中央情报局局长?” 你会得到一个直接的答案。 但是,“只读”属性无法做到的是在CIA中进行更改。 例如,你不能打个电话,突然想要让金·卡戴珊担任总监,或者希望巴黎·希尔顿担任总司令。 想象一下,所有的中情局信息都logging在一张纸上。 基本上,如果您没有“写入”权限,则不能在该纸上添加/减less/编辑或写入任何内容。 如果读取访问是唯一的事情,好难的怜悯。

  • 如果属性给了你“写”访问,那么你可以做到这一点。

    换句话说,访问者允许您向不允许外部人员进入的组织进行查询或进行更改。

类内的对象可以很容易地访问对方

  • 另一方面,如果你已经进入中央情报局,那么你可以轻松地打电话给你在喀布尔的中央情报局工作人员,问他是否想下class后和当地喀布尔的情报人员一起喝啤酒。 但是如果你不在中央情报局,你根本就不会被允许进入:你将无法知道他们是谁(阅读权限),你将无法改变他们的使命(写入权限)。

与类完全相同的东西,你可以访问它们中的variables,属性和方法。

我希望有帮助!

只需attr-accessor为指定的属性创buildgettersetter方法

简单地说,它会为class级定义一个setter和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 

等同于为这个类定义一个setter和getter。

理解它的另一种方法是通过使用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'... 

ownerbalance在技​​术上不是一种方法 ,而是一种属性。 BankAccount类没有def ownerdef balance 。 如果是这样,那么你可以使用下面的两个命令。 但是这两种方法都不存在 但是,您可以像访问通过attr_accessor的方法一样访问属性! 因此,这个词attr_accessor 。 属性。 访问。 它像访问一个方法一样访问属性。

添加attr_accessor :balance, :owner允许您读写balanceowner “方法”。 现在你可以使用最后2个方法。

 $ bankie.balance $ bankie.owner 

为这个模块定义一个命名属性,名称是symbol.id2name,创build一个实例variables(@name)和一个相应的访问方法来读取它。 还创build一个名为name =的方法来设置属性。

 module Mod attr_accessor(:one, :two) end Mod.instance_methods.sort #=> [:one, :one=, :two, :two=] 

总结一个属性访问器又名attr_accessor给你两个免费的方法。

像Java一样,他们被称为getter和setter。

很多答案都显示了很好的例子,所以我只是简单地介绍一下。

#the_attribute

#the_attribute =

在老ruby文档中,哈希标签#表示一种方法。 它也可以包含一个类名前缀… MyClass#my_method

属性和访问器方法

属性是可以从对象外部访问的类组件。 它们被称为许多其他编程语言的属性。 它们的值可以通过使用“点符号”来访问,如在object_name.attribute_name中。 与Python和其他几种语言不同,Ruby不允许直接从对象之外访问实例variables。

 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类的一个实例(对象)。 我们尝试从对象之外读取wheels实例variables的值,但是尝试失败。 发生了什么事是Ruby尝试调用c对象中的一个名为wheels的方法,但是没有定义这样的方法。 简而言之,object_name.attribute_name会尝试在对象内调用名为attribute_name的方法。 为了从外部访问车轮variables的值,我们需要用这个名称来实现一个实例方法,这个方法在调用的时候会返回那个variables的值。 这就是所谓的访问方法。 在一般的编程环境中,从对象外部访问实例variables的常用方法是实现访问器方法,也称为getter和setter方法。 getter允许从外部读取类中定义的variables的值,并且setter允许从外部写入。

在下面的例子中,我们将getter和setter方法添加到Car类中,以从对象外部访问车轮variables。 这不是定义getter和setter的“Ruby方法”; 它只是为了说明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 

上面的例子工作,类似的代码通常用于创build其他语言的getter和setter方法。 但是,Ruby提供了一个更简单的方法:三个内置方法,分别称为attr_reader,attr_writer和attr_acessor。 attr_reader方法使外部可读的实例variables,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,它将是只写的。 这三个方法本身并不是getter和setter,而是在被调用时为我们创build了getter和setter方法。 他们是dynamic(编程)生成其他方法的方法; 这就是所谓的元编程。

第一个(较长)的例子,不使用Ruby的内置方法,只能在getter和setter方法需要额外的代码时使用。 例如,setter方法可能需要在为实例variables赋值之前validation数据或进行一些计算。

通过使用instance_variable_get和instance_variable_set内置方法,可以从对象外部访问(读取和写入)实例variables。 然而,这是很less合理的,通常是一个坏主意,因为绕过封装往往会造成各种各样的破坏。

请在下面findBankAccount的例子。 在attr_accessor中,名称和地址被定义,所以在创build一个对象时它们被传递给对象。 另外还有用于执行读取和写入操作的目的。 对于attr_reader,属性在类的对象的初始化期间被传递给对象。


    class级帐户

       attr_accessor:name,:address
       attr_reader:id,:余额 

       def初始化(名称,地址)
         self.name = name
         self.address =地址
         @平衡= 0
         @id = Random.rand(100)
      结束

       def deposit(money)
         @平衡+ =金钱 
        把“存款Rs#{金钱}” 
      结束

       def check_balance
        提出“可用余额是Rs#{余额}” 
      结束
    结束

     account1 = Account.new('John','新加坡')
     account1.deposit(100)
     account1.check_balance

嗯。 很多很好的答案。 这是我的几分钱。

  • attr_accessor是一个简单的方法,可以帮助我们清理( DRY重复的getter and setter方法。

  • 所以我们可以把更多的精力放在编写业务逻辑上,而不用担心安装者和获取者。

attr_accessor的主要function是从其他文件访问数据。
所以你通常会有attr_reader或者attr_writer,但是好消息是Ruby允许你将这两者和attr_accessor结合在一起。 我认为这是我的方法,因为它更全面或多function。 另外,请记住,在Rails中,这被淘汰,因为它在后端为你做。 所以换句话说:你最好使用attr_acessor而不是另外两个,因为你不用担心具体的问题,访问者就可以覆盖它。 我知道这更多的是一个一般的解释,但它帮助我作为一个初学者。

希望这有助于!