在Ruby的类作用域中使用@variable正确吗?
我经常看到ruby项目在ruby类的类作用域中使用实例变量@var 我认为在类方法中,应该使用类变量@var,而在实例方法中,应该使用实例变量@var 我想知道在类范围中使用@var是否正确 目前我知道在类作用域中使用实例变量和类变量的区别在于实例变量不能被子类继承。代码演示了差异在Ruby的类作用域中使用@variable正确吗?,ruby,Ruby,我经常看到ruby项目在ruby类的类作用域中使用实例变量@var 我认为在类方法中,应该使用类变量@var,而在实例方法中,应该使用实例变量@var 我想知道在类范围中使用@var是否正确 目前我知道在类作用域中使用实例变量和类变量的区别在于实例变量不能被子类继承。代码演示了差异 class Foo @bar = 8 @@bar2 = 10 def self.echo_bar p @bar end def self.echo_bar2 p @@bar2
class Foo
@bar = 8
@@bar2 = 10
def self.echo_bar
p @bar
end
def self.echo_bar2
p @@bar2
end
end
class Foo2 < Foo
end
Foo.echo_bar
Foo.echo_bar2
Foo2.echo_bar
Foo2.echo_bar2
# Result:
# 8
# 10
# nil
# 10
class-Foo
@巴=8
@@bar2=10
def self.echo_条
p@bar
结束
def self.echo_bar2
p@@bar2
结束
结束
类别Foo2
Ruby对象是:
class Foo
@bar = 8
def self.get_bar
@bar
end
end
class FooChild < Foo
end
您将获得以下数据模型(不完全是这样,Foo的祖先及其特征类的层次结构已被删除):
类作用域中的实例变量定义该类对象的私有数据。从上面的模型中,可以通过Foo的特征类中定义的实例方法以及其祖先链类、模块、对象、内核、BasicObject
访问该实例变量。这些实例变量定义了一些与类对象Foo
关联的数据
以书面形式:
class Foo
@bar = 8
def self.get_bar
@bar
end
end
class FooChild < Foo
end
实例变量在类内部定义,但在名为
类实例变量的实例方法外部定义
使用类实例变量和类变量的优势在于使用继承时。您也可以在子类中使用类实例变量,但这看起来很混乱
这不完全是一种继承。Ruby实现有点棘手。Ruby中的实例变量是在赋值时创建的
任何子类都可以更改共享类变量的值,但只会为特定类创建类实例变量。因此,请注意在类中变量需要什么行为
和类变量相比,类实例变量的缺点是它们不能在实例方法内部使用。除此之外,您还可以将它们与常规实例变量混淆
class Foo
@class_instance_var_1 = 0
@class_instance_var_2 = 0
@@class_var = 10
def initialize
@class_instance_var_1 = 1 # cannot change it here
@@class_var = 100
end
def self.change
@class_instance_var_2 = 2 # can change here
@@class_var = 200
end
def self.echo_var
p 'class_instance_var_1=' + @class_instance_var_1.to_s
p 'class_instance_var_2=' + @class_instance_var_2.to_s
p 'class_var=' + @@class_var.to_s
end
end
puts '--- initial status of Foo'
Foo.echo_var
puts '--- initialized Foo'
Foo.new
Foo.echo_var
puts '--- changed Foo'
Foo.change
Foo.echo_var
class Foo2 < Foo
@class_instance_var_2 = 22 # can set here only but not in Foo
@@class_var = 20 # can change here and everywhere
end
puts '--- after Foo2 implementation'
puts '--- Foo'
Foo.echo_var
puts '--- Foo2'
Foo2.echo_var
class Foo3 < Foo2
@class_instance_var_2 = 33 # can set here only but not in Foo
@@class_var = 30 # can change here and everywhere
end
puts '--- after Foo3 implementation'
puts '--- Foo'
Foo.echo_var
puts '--- Foo2'
Foo2.echo_var
puts '--- Foo3'
Foo3.echo_var
当然,这可能是正确的方法,这取决于上下文。在rails中,我几乎看到@var在类作用域中使用,可能只是因为@var看起来很难看?这与它的外表毫无关系。实例变量和类变量的语义完全不同,您无法交换它们。在Rails中,您将看不到类变量,因为首选class\u attribute
(ActiveSupport定义的方法)<创建代码>class_属性
是因为类变量在超类和子类之间共享,因此子类中对其值的修改也应用于超类,这是很少需要的。使用class\u属性
可以避免这种影响最好使用singleton\u类
而不是eigenclass
,因为甚至有一个方法具有该名称
class Foo
@class_instance_var_1 = 0
@class_instance_var_2 = 0
@@class_var = 10
def initialize
@class_instance_var_1 = 1 # cannot change it here
@@class_var = 100
end
def self.change
@class_instance_var_2 = 2 # can change here
@@class_var = 200
end
def self.echo_var
p 'class_instance_var_1=' + @class_instance_var_1.to_s
p 'class_instance_var_2=' + @class_instance_var_2.to_s
p 'class_var=' + @@class_var.to_s
end
end
puts '--- initial status of Foo'
Foo.echo_var
puts '--- initialized Foo'
Foo.new
Foo.echo_var
puts '--- changed Foo'
Foo.change
Foo.echo_var
class Foo2 < Foo
@class_instance_var_2 = 22 # can set here only but not in Foo
@@class_var = 20 # can change here and everywhere
end
puts '--- after Foo2 implementation'
puts '--- Foo'
Foo.echo_var
puts '--- Foo2'
Foo2.echo_var
class Foo3 < Foo2
@class_instance_var_2 = 33 # can set here only but not in Foo
@@class_var = 30 # can change here and everywhere
end
puts '--- after Foo3 implementation'
puts '--- Foo'
Foo.echo_var
puts '--- Foo2'
Foo2.echo_var
puts '--- Foo3'
Foo3.echo_var
--- initial status of Foo
"class_instance_var_1=0"
"class_instance_var_2=0"
"class_var=10"
--- initialized Foo
"class_instance_var_1=0"
"class_instance_var_2=0"
"class_var=100"
--- changed Foo
"class_instance_var_1=0"
"class_instance_var_2=2"
"class_var=200"
--- after Foo2 implementation
--- Foo
"class_instance_var_1=0"
"class_instance_var_2=2"
"class_var=20"
--- Foo2
"class_instance_var_1="
"class_instance_var_2=22"
"class_var=20"
--- after Foo3 implementation
--- Foo
"class_instance_var_1=0"
"class_instance_var_2=2"
"class_var=30"
--- Foo2
"class_instance_var_1="
"class_instance_var_2=22"
"class_var=30"
--- Foo3
"class_instance_var_1="
"class_instance_var_2=33"
"class_var=30"