关于ruby类变量的混淆
假设一个使用类变量的简单ruby程序关于ruby类变量的混淆,ruby,class-variables,Ruby,Class Variables,假设一个使用类变量的简单ruby程序 class Holder @@var = 99 def Holder.var=(val) @@var = val end def var @@var end end @@var = "top level variable" a = Holder.new puts a.var 我猜结果应该是99,但输出不是99。我想知道为什
class Holder
@@var = 99
def Holder.var=(val)
@@var = val
end
def var
@@var
end
end
@@var = "top level variable"
a = Holder.new
puts a.var
我猜结果应该是
99
,但输出不是99
。我想知道为什么。由于类变量的作用域是类,我假定行@@var=“top level variable”
不会影响类中的变量。@@var
是Holder
的类变量。顶层的@@var
不是Holder
的同名类变量@@var
,而是您正在为类对象创建一个全新的类变量。现在@@var
与父类的子类共享Object
是类Holder
的父类。在Ruby中,如果没有显式定义任何自定义类的超类,则使用class
关键字进行定义,然后Object
类成为该类的默认超类,您只需创建
在顶层,您正在类对象中定义一个新的类变量,就像您在发布的示例中所做的那样。通过继承,类持有者现在可以使用它
我是说,当你写下以下内容时:
class Holder
@@var = 99
def Holder.var=(val)
@@var = val
end
def var
@@var
end
end
@@var
尚未添加到对象
类中。现在在顶层,当您写下以下行时:
@@var = "top level variable"
这意味着,您正在将它添加到对象
类中,并更新旧变量(@@var
)与持有者
类一中相同的名称,使用这个新变量,您刚刚在对象
类的范围中定义
请记住,类变量是共享变量,仅对类(B
)可见,您在其中定义了它及其子类(C
),子类(C
)的子类(D
)等等。但在父类(A
)中定义了与子类(B
)中相同的名称变量之前,类(B
)的超类(A
)不可见
A类
结束
B类
我想详述其他人所说的,特别是比较类变量和类实例变量的使用。让我们从这个开始:
class Holder1
end
class Holder2 < Holder1
@@var = 99
# Create a class setter and a getter for the class variable
def Holder2.var=(val)
@@var = val
end
def Holder2.var
@@var
end
# Create a instance getter for the class variable
def var
@@var
end
end
class Holder3 < Holder2
end
Holder2.var #=> 99
Holder2.var = 1
Holder3.var #=> 1
Holder1.var #=> NoMethodError: undefined method `var' for Holder1:Class
Holder2.new.var #=> 1
Holder3.new.var #=> 1
Holder3.var = 2
Holder3.var #=> 2
Holder2.var #=> 2
Holder3.new.var #=> 2
Holder2.new.var #=> 2
这是因为在创建方法时,self
=>Holder2
。通过不硬连接类名,如果决定重命名该类,则无需进行任何更改
现在,这(类变量的使用)可能正是您想要的行为。也就是说,如果您希望子类看到变量并能够对其进行更改,则需要一个类变量
但是,如果希望每个子类都有自己的变量,子类既不能看到也不能更改这些变量,则需要使用类实例变量@var
,而不是类变量@@var
。(从技术上讲,这并不完全正确,因为可以在程序中的任何位置使用Holder2.instance\u variable\u get(:@var)
或Holder2.instance\u variable\u set(:@var)
)
将下面代码的结果与上面代码的结果进行比较。我包含了一个与类实例变量同名的实例变量,@var
,以说明它们与@night
和@day
一样不同
class Holder1
end
class Holder2 < Holder1
# Create an accessor for the instance variable
attr_accessor :var
# Initialize class instance variable
@var = 99
# Create an accessor for the class instance variable
class << self
puts "self in 'class << self': #{self}"
attr_accessor :var
def our_dog
"Diva"
end
end
# Create a class method
def self.our_cat
puts "self in 'self.our_cat())' def: #{self}"
"Teagan"
end
# Create an instance setter and a getter for the class instance variable
def c_ivar=(val)
self.class.var = val
end
def c_ivar
self.class.var
end
end
class Holder3 < Holder2
end
#=> self in 'class << self': #<Class:Holder2>
Holder2.var #=> 99
h2 = Holder2.new
h2.var #=> nil
Holder2.var = 1
Holder2.var #=> 1
h2.c_ivar #=> 1
h2.c_ivar = 2
Holder2.var #=> 2
h2.var #=> nil
h2.var = 3
h2.var #=> 3
Holder2.var #=> 2
Holder3.var #=> nil
Holder1.var #=> NoMethodError: undefined method `var' for Holder1:Class
Holder3.var = 4
Holder3.var #=> 4
Holder2.var #=> 2
h3 = Holder3.new
h3.c_ivar #=> 4
h2.c_ivar #=> 2
Holder3.our_dog #=> "Diva"
Holder3.our_cat #=> "self in 'self.our_cat())' def: Holder3"
#=> "Teagan"
这表明our_cat()。因此,有人说,从技术上讲。这也告诉我们,我们可以将my_cat
的定义移到类中
def self.var=(val)
@@var = val
end
def self.var
@@var
end
class Holder1
end
class Holder2 < Holder1
# Create an accessor for the instance variable
attr_accessor :var
# Initialize class instance variable
@var = 99
# Create an accessor for the class instance variable
class << self
puts "self in 'class << self': #{self}"
attr_accessor :var
def our_dog
"Diva"
end
end
# Create a class method
def self.our_cat
puts "self in 'self.our_cat())' def: #{self}"
"Teagan"
end
# Create an instance setter and a getter for the class instance variable
def c_ivar=(val)
self.class.var = val
end
def c_ivar
self.class.var
end
end
class Holder3 < Holder2
end
#=> self in 'class << self': #<Class:Holder2>
Holder2.var #=> 99
h2 = Holder2.new
h2.var #=> nil
Holder2.var = 1
Holder2.var #=> 1
h2.c_ivar #=> 1
h2.c_ivar = 2
Holder2.var #=> 2
h2.var #=> nil
h2.var = 3
h2.var #=> 3
Holder2.var #=> 2
Holder3.var #=> nil
Holder1.var #=> NoMethodError: undefined method `var' for Holder1:Class
Holder3.var = 4
Holder3.var #=> 4
Holder2.var #=> 2
h3 = Holder3.new
h3.c_ivar #=> 4
h2.c_ivar #=> 2
Holder3.our_dog #=> "Diva"
Holder3.our_cat #=> "self in 'self.our_cat())' def: Holder3"
#=> "Teagan"
Holder2.singleton_methods #=> [:var, :var=, :our_dog, :our_cat]
module M
attr_accessor :var
def our_dog
"Diva"
end
end