为什么我不能使用ruby
方法或accessor
直接在instance_variable_get
中访问实例变量?
class Foo
@my_var
end
为什么我们不能在这个例子中使用Foo.@my_var
?
答案 0 :(得分:2)
OP提供的示例是类实例变量。这些只能通过类方法访问。
"定期"属性访问者不允许从课外访问。以下是创建有效的访问器的几种方法:
class A
@class_instance_var = "foo"
class << self
attr_accessor :class_instance_var
end
end
puts A::class_instance_var # Output: foo
OR
class A
@class_instance_var = "foo"
def self.class_instance_var
@class_instance_var
end
end
puts A::class_instance_var # Output: foo
类实例变量名也以@开头。但是,它们是在类级别定义的,不在任何方法之外。类实例变量只能通过类方法访问。它们在类的所有实例之间共享,但不在其子类之间共享。换句话说,它们不是可继承的。如果在类的一个实例中更改了类实例变量的值,则会影响所有其他实例。之前我们看到所有类都是一个名为Class的内置类的实例。这就是使类实例变量成为可能的原因。
class Vehicle
@count = 0 # This is a class instance variable
def initialize
self.class.increment_count
self.class.show_count
end
def self.increment_count # This is a class method
@count += 1
end
def self.show_count # This is a class method
puts @count
end
end
class Car < Vehicle
@count = 0
end
v1 = Vehicle.new # Output: 1
v2 = Vehicle.new # Output: 2
v3 = Vehicle.new # Output: 3
car1 = Car.new # Output: 1
car2 = Car.new # Output: 2
v3 = Vehicle.new # Output: 4
让我们回顾一下上面的例子。在Vehicle类中设置了一个名为@count的类实例变量,初始值为0.每次实例化Vehicle类时,initialize方法调用self.increment_count来增加@count的值,并使用self.show_count返回新的价值。然后,我们有Car类,它是Vehicle的子类,并继承了它的所有方法。但是,它不会继承@count类实例变量,因为这种类型的变量不可继承。这就是为什么计数器在Car类中起作用的原因,但它有自己的计数。
以self为前缀的方法,例如self.increment_count和self.show_count,是类方法。这是唯一能够访问类实例变量的方法。
答案 1 :(得分:1)
那不是语言的构建方式。也许看看openstruct
require 'ostruct'
obj = OpenStruct.new(my_var: 1)
obj.my_var
# => 1
顺便提一下,您设置实例变量的方法不正确。您应该只在实例方法或initialize
中设置实例变量,否则使用类变量或常量。
使用常量的示例:
class Foo
MyVar = 1
end
Foo::MyVar
# => 1
您还可以Foo.new.@my_var
使用method_missing
:
class Foo
def method_missing(m, *args, &block)
self.instance_variable_get(m)
end
def initialize
@my_var = 1
end
end
Foo.new.@my_var
# => 1