Ruby中的访问器?

我很难理解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

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

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

即使这可能会重复。 当你想让读写器都使用accessor!

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_readerattr_writerattr_accessor方法如何为您生成方法,请阅读其他答案,书籍和ruby文档。


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

诀窍是, class不是Ruby中的定义(它仅仅是C ++和Java等语言中的一个定义),但它是一个表达式。 正是在这个评估过程中,调用了attr_accessor方法,这反过来修改了当前类 - 记住隐式接收方: self.attr_accessor ,其中self是此时的“open”类对象。

attr_accessor和朋友的需求,很好:

  • Ruby和Smalltalk一样,不允许在该对象的methods1之外访问实例变量。 也就是说,实例变量无法以xy格式访问,就像在Java或甚至Python中常见的那样。 在Ruby中, y总是作为一个消息发送(或“调用方法”)。 因此, attr_*方法通过动态创建的方法创建代理实例@variable访问的包装器。

  • 锅板很烂

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


    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
    

    你可以在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
    
    链接地址: http://www.djcxy.com/p/645.html

    上一篇: accessor in Ruby?

    下一篇: How to get a password from a shell script without echoing