为什么我们需要attr

我不明白为什么我们需要在类中声明attr_reader和attr_writer或attr_accessor。 我阅读了这篇文章和这篇文章,但这些文章主要解释了他们的工作方式,而不是为什么他们在那里工作。

的情况下

class Person
  attr_accessor :age
end

bob = Person.new
bob.age = 99
bob.age

看起来有点多余,不得不告诉Ruby编写和读取年龄,而不能自动在类之外编写和读取实例变量。 为什么我们需要在Class中设置读写器而不是下面的代码并保存几行?

class Person
end

bob = Person.new
bob.age = 99
bob.age 

因为它使代码更易于维护。

通过这种方式,您可以清楚地看到您希望发生的类代码,并期望其他类可以访问这些变量。

如果没有这个外部代码可以简单地访问你的内部变量,那么如果你重构你的代码并删除或重命名这样一个变量,外部代码就会中断。

因此,访问方法明确表示您打算让其他类访问这些方法

仅供参考:Ruby非常强大,如果你想要,你可以继续并按照你想要的方式工作。 我不推荐这个,但是我指出它,所以你会明白它的明确选择是为了保持代码的可读性。 但是,如果你想看看你如何做到这一点,并尝试运行代码...

<script type="text/ruby">

def puts(s)  # ignore this method, just dumps to the display
  Element['#output'].html = Element['#output'].html + s.to_s + "<br/>"
end

class OpenKimono
  def method_missing(name, *args)
    if name =~ /=$/
      instance_variable_set("@#{name[0..-2]}".to_sym, args[0])
    else
      instance_variable_get("@#{name}")
    end
  end
end

class MyClass < OpenKimono
end

foo = MyClass.new

foo.bar = 12

puts "foo.bar just set to 12, it now = #{foo.bar}"

foo.baz = 13

puts "foo.baz just set to 13, it now = #{foo.baz}"

puts "foo.manchu has never been set... what does it equal? #{foo.manchu}"

</script>


<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://rawgit.com/reactive-ruby/inline-reactive-ruby/master/inline-reactive-ruby.js"></script>
<div id="output" style="font-family: courier"></div>

OpenStruct的行为类似于OP的第二个片段:

require 'ostruct'

bob = OpenStruct.new
bob.age = 99
p bob.age # => 99

所以有一个选择。


在许多OO语言中,您有一个在对象的方法和对象的属性之间共享的表。 在Ruby中,所有对象的使用者都应该关心对象的方法。 如果你在JS中有这个:

Tank:
   weight: 123
   moveForward: function()...

在Ruby中你将拥有:

Tank:
  ivars:
     @weight = 123
  methods:
     weight: return @weight # or other implementation, or a proxy...
     move_forward...

具有两个不同表的原因是允许对象决定如何存储数据以及是否存储数据,而不是从外部抽取属性。 这允许一个非常重要的优点:维持UAP。 也就是说,从外部使用对象的方法(发送消息),无论这些方法是属性还是方法。

这是一个奇妙的特性,许多其他面向对象语言或者以优化(避免间接)或疏忽/无知(python就是一个主要例子)的名义而忽视它。 我在这里写了一篇关于这个主题的文章:http://live.julik.nl/2012/08/messages-versus-slots

回答你问题的最后部分:

为什么我们需要在Class中设置读写器而不是下面的代码并保存几行?

为了防止你一直在JavaScript中使用某个方法或某个对象上的某个属性的情况,只能在它的位置找到undefined的位置,这会导致应用程序在您访问属性的地方出现很多行(或执行秒) 。

在Ruby中,如果你这样做,你会得到一个异常,它会从你自己中拯救你几千次,相信我。 事实上,你可以创建一个接受任何getter / setter消息的对象,并且这个对象已经存在 - 它是一个OpenStruct。 由于速度问题,这通常不是一种好的做法。

[1] pry(main)> require 'ostruct'
=> true
[2] pry(main)> s = OpenStruct.new
=> #<OpenStruct>
[3] pry(main)> s.foo = 1
=> 1
[4] pry(main)> s.bar = 2
=> 2
[5] pry(main)> s.foo
=> 1
[6] pry(main)> s.bar
=> 2
[7] pry(main)> s.x
=> nil

使用属性方法生成器的另一个好处是,大多数Ruby文档引擎(RDoc和YARD)都会寻找这些引擎来更快地记录对象方法。

链接地址: http://www.djcxy.com/p/25731.html

上一篇: Why do we need attr

下一篇: Presentation of ruby/rails objects?