为了解决您的“如果它们是变量是真的”和“范围”问题,回答访问器符号与实例变量无关会更简单,即使这听起来是反传统的。它们不指向实例变量。访问器只定义 getter 和 setter方法。在 Object#instance_variables 下,Pickaxe(*) 表示:请注意,简单地定义访问器不会创建相应的实例变量。
在 Ruby 中,变量只有在您为其赋值时才会存在。下面的代码演示了这一点。
class MyClass
attr_accessor :name
attr_reader :book
end
obj = MyClass.new # line 6
print '1) obj.instance_variables : '; p obj.instance_variables
print '2) obj.name : '; p obj.name
obj.name = 'xyz'
print '3) obj.instance_variables : '; p obj.instance_variables
print '4) obj.name : '; p obj.name
print '5) obj.book : '; p obj.book
class MyClass
def initialize(p_book)
@book = p_book
end
end
obj = MyClass.new('The Pickaxe') # line 21
print '6) [new] obj.book : '; p obj.book
class MyClass
method_name = 'title'
attr_accessor method_name # line 26
end
obj.title = 'Programming Ruby'
print '7) obj.instance_variables : '; p obj.instance_variables
print '8) obj.title : '; p obj.title
输出 :
$ ruby -w t.rb
1) obj.instance_variables : []
2) obj.name : nil
3) obj.instance_variables : ["@name"]
4) obj.name : "xyz"
5) obj.book : nil
6) [new] obj.book : "The Pickaxe"
7) obj.instance_variables : ["@title", "@book"]
8) obj.title : "Programming Ruby"
1) 空数组:访问者没有定义实例变量
2) 询问实例变量 @name 回答 nil :它不存在
3) 赋值已经创建了实例变量。
请注意,这name =
是将 setter 用作带有参数的普通方法的语法糖:obj.name=('xyz')
4) getter 方法name
回答 @name 的值
5) getter 方法book
回答 nil 因为实例变量 @book 不存在。定义访问attr_reader :book
器尚未定义相应的实例变量
6) getter 方法回答在 21 中调用的book
赋值。实例变量 @book 已由initialize
new
@book = p_book
第 26 行)我一直认为访问器只接受符号。我发现变量是可能的,但兴趣有限。
7) setter 方法title=
创建了@title。这也表明实例变量属于单个对象。我们经常相信它们属于类的所有实例,就像在其他语言中一样。在这种情况下,@name 只属于第 6 行创建的对象。
8) getter 方法title
回答@title 的值
class MyClass
def title # line 34
@book + ' (cheating !)'
end
end
print '9) obj.title : '; p obj.title
输出 :
t.rb:34: warning: method redefined; discarding old title
9) obj.title : "The Pickaxe (cheating !)"
9) 当然,访问器符号和相应的实例变量之间存在紧密的关联,因为在幕后,Ruby 创建了引用同名实例变量的方法。您可以定义自己的吸气剂和作弊方法。
请注意,除了类变量(@@var,有些人不喜欢它们和全局变量一样丑),类也可以有实例变量。我称它们为类实例变量:)。
class MyClass
: Ruby 分配类 Class 的一个新实例,定义一个常量 MyClass,并将新实例分配给该常量。因此 MyClass 是一个普通对象(Class 的实例),因此可以具有实例变量。
if RUBY_VERSION[0..2] == '1.8'
class Object
def singleton_class
class << self
self
end
end
end
end
class MyClass
singleton_class.instance_eval do
attr_accessor :counter
end
@counter = 0
def initialize(p_book)
@book = p_book
self.class.counter += 1
end
end
print '10) MyClass.singleton_methods : '; p MyClass.singleton_methods
print '11) MyClass.instance_variables : '; p MyClass.instance_variables
obj = MyClass.new('Ruby')
print '12) [new] obj.book ', MyClass.counter, ': '; p obj.book
obj = MyClass.new('Metaprogramming')
print '13) [new] obj.book ', MyClass.counter, ': '; p obj.book
输出 :
t.rb:55: warning: method redefined; discarding old initialize
10) MyClass.singleton_methods : ["counter", "counter="]
11) MyClass.instance_variables : ["@counter"]
12) [new] obj.book 1: "Ruby"
13) [new] obj.book 2: "Metaprogramming"
更多关于单例方法的信息:def `self.function` 名称是什么意思?
(*) http://pragprog.com/book/ruby3/programming-ruby-1-9