Rails_Xattr_accessor_方法小结

 

一。基础知识:实例变量的特殊性:

ruby中的实例变量,是在实例变量的表中去寻找的。这样,一个@name在没有定义的时候,寻找的结果是nil,而不是异常。

但是,如果没有定义类变量@@buffer,则会抛出异常。

 

class MAttrAccessorTest
  #ok~
  puts @name #=>nil
  #ERROR
  puts @@buffer #=>uninitialized class variable @@aaa in MAttrAccessorTest (NameError)
end
 

 

二。attr_accessor,自动给实例变量加入get set 方法

例子:

 

class AttrAccessorTest
  attr_accessor :name, :age

  #get method
  def love
    @love
  end
  #set method
  def love=(love)
    @love = love
  end
end
 

 

输出:

user = AttrAccessorTest.new

user.name = "June"

puts user.inspect

puts user.age #=>nil

 

puts user.inspect

user.age = 29

puts user.age

puts user.inspect

 

 

三。mattr_accessor :user_buffer

这个方法会在module中定义一个类变量:@@user_buffer;

同时定义对这个类变量的get,set方法,注意是实例方法。

这样,当包含这个模块的时候,会有@@user_buffer这个类变量,和get/set方法。

因为类变量是给所有实例共享的,所以某个实例修改这个类变量后,其他实例访问到的类变量也发生变化了。

 

例子:

module MAttrAccessorTest
  mattr_accessor :user_buffer
 
  #这个时候这里不会报错了!!!
  puts @@user_buffer
end
 
class AttrAccessorTest
  include MAttrAccessorTest
end
 
user1 = AttrAccessorTest.new
user2 = AttrAccessorTest.new
 
puts "user1.user_buffer = #{user1.user_buffer.inspect}"
puts "user2.user_buffer = #{user2.user_buffer.inspect}"
 
user1.user_buffer = []
user1.user_buffer << "Fantaxy"
puts "user1.user_buffer = #{user1.user_buffer.inspect}"
puts "user2.user_buffer = #{user2.user_buffer.inspect}"
 
user2.user_buffer << "June"
puts "user1.user_buffer = #{user1.user_buffer.inspect}"
puts "user2.user_buffer = #{user2.user_buffer.inspect}"
 

输出:

nil

user1.user_buffer = nil

user2.user_buffer = nil

user1.user_buffer = ["Fantaxy"]

user2.user_buffer = ["Fantaxy"]

user1.user_buffer = ["Fantaxy", "June"]

user2.user_buffer = ["Fantaxy", "June"]

 

 

四。cattr_accessor :user_buffer

同mattr_accessor,只不过是使用在了类中。

 

例子:

class AttrAccessorTest
  mattr_accessor :user_buffer
 
  #这个时候这里不会报错了!!!
  puts @@user_buffer
end
 
user1 = AttrAccessorTest.new
user2 = AttrAccessorTest.new
 
puts "user1.user_buffer = #{user1.user_buffer.inspect}"
puts "user2.user_buffer = #{user2.user_buffer.inspect}"
 
user1.user_buffer = []
user1.user_buffer << "Fantaxy"
puts "user1.user_buffer = #{user1.user_buffer.inspect}"
puts "user2.user_buffer = #{user2.user_buffer.inspect}"
 
user2.user_buffer << "June"
puts "user1.user_buffer = #{user1.user_buffer.inspect}"
puts "user2.user_buffer = #{user2.user_buffer.inspect}"
 
输出:
nil
user1.user_buffer = nil
user2.user_buffer = nil
user1.user_buffer = ["Fantaxy"]
user2.user_buffer = ["Fantaxy"]
user1.user_buffer = ["Fantaxy", "June"]
user2.user_buffer = ["Fantaxy", "June"]
 

输出:

nil

user1.user_buffer = nil

user2.user_buffer = nil

user1.user_buffer = ["Fantaxy"]

user2.user_buffer = ["Fantaxy"]

user1.user_buffer = ["Fantaxy", "June"]

user2.user_buffer = ["Fantaxy", "June"]

 

五。class_inheritable_accessor

不要使用这个为好:

#1,貌似有bug 

#2,晦涩且复杂度高,容易出错

 

 

class Parent
  class_inheritable_accessor :name, :age
  self.name = "Human" #注意这里必须先赋值,否则就不灵了哦,请对比:superclass_delegating_accessor
  self.age  = "2000_000 years"

  def to_s
    "name = #{name}, age = #{age}"
  end
end

class Child < Parent

end

parent = Parent.new
puts "parent: #{parent}"
parent.name = "JRuby Programmer"
parent.age  = "3 years ago"
puts "parent: #{parent}"

puts "----"
child1 = Child.new
child2 = Child.new
puts "child1: #{child1}"
puts "child2: #{child2}"

puts "----"
child1.name = "Programmer"
child1.age  = "100 years ago"
puts "child1.name = #{child1.name}, child1.age = #{child1.age}"
puts "child2.name = #{child2.name}, child2.age = #{child2.age}"

puts "----"
child2.name = "Java Programmer"
child2.age  = "From 1991"
puts "child1.name = #{child1.name}, child1.age = #{child1.age}"
puts "child2.name = #{child2.name}, child2.age = #{child2.age}"
 

六。superclass_delegating_accessor

这个也被rails3废弃了。

 

附:

mattr_accessor和cattr_accessor源码简析:

#1 在Class中加入了实例方法:mattr_accessor/cattr_accessor

#2 这些实例方法对于每个类来说,属于类方法

#3 这些类方法能在类的作用域内使用,格式如:mattr_accessor :user_buffer, :visit_buffer

#4 这些方法本身使用class_eval/module_eval往类中加入实例方法,即get/set方法

#5 这些get/set方法操作的变量都是类变量,能被其所有类和实例共享

 

另外:

如果使用:instance_writer => false 则表示关闭实例对类变量的写权限

例子: mattr_accessor :user_buffer, :instance_writer => false

 

+

+

+

*

+

+

+

 

 

你可能感兴趣的:(Access)