Our Point class uses two instance variables. As we've noted, however, the value of these variables are only accessible to other instance methods. If we want users of the Point class to be able to use the X and Y coordinates of a point, we've got to provide accessor methods that return the value of the variables:
class Point
def initialize(x,y)
@x, @y = x, y
end
def x # The accessor (or getter) method for @x
@x
end
def y # The accessor method for @y
@y
end
end
p = Point.new(1,2) q = Point.new(p.x*2, p.y*3)
class MutablePoint
def initialize(x,y); @x, @y = x, y; end
def x; @x; end # The getter method for @x
def y; @y; end # The getter method for @y
def x=(value) # The setter method for @x
@x = value
end
def y=(value) # The setter method for @y
@y = value
end
end
p = Point.new(1,1) p.x = 0 p.y = 0
This combination of instance variable with trivial getter and setter methods is so common that Ruby provides a way to automate it. The attr_reader and attr_accessor methods are defined by the Module class. All classes are modules, (the Class class is a subclass of Module) so you can invoke these method inside any class definition. Both methods take any number of symbols naming attributes. attr_reader creates trivial getter methods for the instance variables with the same name. attr_accessor creates getter and setter methods. Thus, if we were defining a mutable Point class, we could write:
class Point attr_accessor :x, :y # Define accessor methods for our instance variables end
class Point attr_reader :x, :y # Define reader methods for our instance variables end
attr_reader "x", "y"
attr :x # Define a trivial getter method x for @x attr :y, true # Define getter and setter methods for @y. Optional boolean is Obsoleted
Theattr,attr_reader, andattr_accessormethods create instance methods for us. This is an example of metaprogramming.
x= podemos sentirnos tentados de utilizarlo
dentro de otro método de instancia de la clase.
That is, instead of writing @x=2, you might write
x=2, intending to invoke x=(2) implicitly on self.
x=2 creates a new
local variable.
self.x=2.
casiano@exthost:~/LPPsrc/221012$ cat -n setters.rb
1 class Tutu
2 attr_accessor :n
3
4 def initialize(n)
5 @n = n
6 end
7
8 def to_s
9 "#{n*2}"
10 end
11
12 def square
13 n = n * n # n here is a local variable!
14 end
15
16 def square2
17 self.n = n * n
18 end
19 end
20
21 if __FILE__ == $0
22 x = Tutu.new(ARGV.shift || 4)
23 puts x # to_s gets called: 8
24 begin
25 x.square
26 rescue
27 puts "Raised exception '#{$!.class}'. Message: <#{$!}>"
28 end
29 x.square2 # 32 = 16 *2
30 puts x
31 end
~/rubytesting/TheRubyProgrammingLanguage/Chapter7ClassesAndModules$ ruby setters.rb 8 Raised exception 'NoMethodError'. Message: <undefined method `*' for nil:NilClass> 32
attr_reader et al. son proveídos por la clase Module.
ruby-1.9.2-head :004 > Class.class
=> Class
ruby-1.9.2-head :005 > Class.superclass
=> Module
ruby-1.9.2-head :006 > Class.superclass.superclass
=> Object
ruby-1.9.2-head :007 > Class.superclass.superclass.superclass
=> BasicObject
ruby-1.9.2-head :008 > Class.ancestors
=> [Class, Module, Object, InteractiveEditor::Editors,
Wirble::Shortcuts,
PP::ObjectMixin,
Kernel, BasicObject]
attr_accessor es un método de instancia o de clase?Casiano Rodriguez León 2015-01-07