Ruby中的attr_访问器是什么?

Ruby中的attr_访问器是什么?,ruby,Ruby,我很难理解Ruby中的attr\u访问器 有人能给我解释一下吗?基本上,他们伪造了可公开访问的数据属性,而Ruby没有这些属性。只是一种方法。(该链接应提供有关其工作原理的更多信息-查看生成的方法对,教程应向您展示如何使用它。) >技巧是类< /C> >不是Ruby中的定义(它是C++语言和java语言中的“一个定义”),但它是一个表达式。在这个求值过程中,调用attr\u访问器方法,然后修改当前类-记住隐式接收者:self.attr\u访问器,其中self是此时的“打开”类对象 对属性访问器

我很难理解Ruby中的
attr\u访问器


有人能给我解释一下吗?

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

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

<> >技巧是类< /C> >不是Ruby中的定义(它是C++语言和java语言中的“一个定义”),但它是一个表达式。在这个求值过程中,调用
attr\u访问器
方法,然后修改当前类-记住隐式接收者:
self.attr\u访问器
,其中
self
是此时的“打开”类对象

对属性访问器和朋友的需求是:

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

  • 样板很烂

  • 希望这能澄清一些小细节。快乐编码



    1严格来说,这不是真的,确实存在,但对“public instance variable”访问没有语法支持。

    attr\u accessor
    非常简单:

    attr_accessor :foo
    
    是以下各项的快捷方式:

    def foo=(val)
      @foo = val
    end
    
    def foo
      @foo
    end
    

    它只是一个对象的getter/setter,它只是一个为实例变量定义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
    

    attr\u 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
    

    假设您有一个class
    Person

    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
      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"
    
    太棒了。现在我们可以使用reader和writer方法编写和读取实例变量
    @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对象中的实例变量
    @name
    将被设置为与手动设置时一样,因此您可以在其他方法中使用它

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

    就这样。为了了解
    attr\u reader
    attr\u writer
    attr\u accessor
    方法实际上是如何为您生成方法的,请阅读其他答案、书籍和ruby文档

    简单地
    attr accessor
    为指定属性创建
    getter
    setter
    方法

    我认为让新rubyist/程序员(像我一样)感到困惑的部分原因是:

    “为什么我不能告诉实例它有任何给定的属性(例如名称),然后一下子给该属性一个值?”

    更一般化一点,但对我来说,这就是它的作用:

    鉴于:

    class Person
    end
    
    我们还没有将“人”定义为具有名称或任何其他属性的事物

    因此,如果我们:

    baby = Person.new
    
    …试着给他们起个名字

    baby.name = "Ruth"
    
    我们得到一个错误,因为在Rubyland中,对象的Person类不是与“名称”相关联或能够具有“名称”的东西。。。然而

    但是我们可以使用任何给定的方法(参见前面的答案)来表示,“Person类(
    baby
    )的实例现在可以有一个名为“name”的属性,因此我们不仅有一种获取和设置该名称的语法方法,而且这样做对我们来说是有意义的。”


    再一次,从稍微不同和更一般的角度回答这个问题,但我希望这有助于下一个找到这条线索的类Person实例。

    简单地说,它将为类定义一个setter和getter

    注意

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


    定义类的setter和getter是等效的。

    如果您熟悉OOP概念,则必须熟悉getter和setter方法。 attr_访问器在Ruby中也做同样的事情

    一般情况下的接受者和接受者

    class Person
      def name
        @name
      end
    
      def name=(str)
        @name = str
      end
    end
    
    person = Person.new
    person.name = 'Eshaan'
    person.name # => "Eshaan"
    
    class Person
      attr_accessor :name
    end
    
    person = Person.new
    person.name = "Eshaan"
    person.name # => "Eshaan"
    
    设置器方法

    def name=(val)
      @name = val
    end
    
    Getter方法

    def name
      @name
    end
    
    Ruby中的Getter和Setter方法

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

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

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

    我也面临着这个问题,并对这个问题写了一个有点长的答案。关于这一点已经有了一些很好的答案,但任何想要进一步澄清的人,我希望我的答案能有所帮助

    初始化方法

    Initialize允许您在创建实例时为对象的实例设置数据,而不必在每次创建类的新实例时在代码中的单独一行上设置数据

    class Person
    
      def initialize(name)
        @name = name
      end
    
    
      def greeting
        "Hello #{@name}"
      end
    end
    
    person = Person.new("Denis")
    puts person.greeting
    
    在上面的代码中,我们使用initialize方法通过initialize中的参数传递Dennis来设置名称“Denis”。如果我们想在不使用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
    
    def name
       "Fido"
    end
    
    在上面的代码中,我们通过使用person.name调用attr_accessor setter方法来设置名称,而不是在初始化对象时设置值

    两种“方法”
    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 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>
    
    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
    
    class Car
      attr_accessor :wheels
    end
    
    f = Car.new
    f.wheels = 4
    f.wheels  # Output: => 4
    
    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'...
    
    $ bankie.balance
    $ bankie.owner
    
    class Foo
      attr_accessor 'myvar'
      def initialize
        @myvar = "A"
        myvar = "B"
        puts @myvar # A
        puts myvar # B - myvar declared above overrides myvar method
      end
    
      def test
        puts @myvar # A
        puts myvar # A - coming from myvar accessor
    
        myvar = "C" # local myvar overrides accessor
        puts @myvar # A
        puts myvar # C
    
        send "myvar=", "E" # not running "myvar =", but instead calls setter for @myvar
        puts @myvar # E
        puts myvar # C
      end
    end
    
    class Nameable
      def self.named(whatvalue)
        define_method :name do whatvalue end
      end
    end
    
    class Dog < Nameable
      named "Fido"
    end
    
    def name
       "Fido"
    end
    
    puts Dog.new.name #=> Fido