gpt4 book ai didi

ruby - 为什么 Ruby 类变量的行为如此奇怪?

转载 作者:数据小太阳 更新时间:2023-10-29 08:48:15 24 4
gpt4 key购买 nike

我只是花了很多时间在 IRB 中玩耍(好吧,实际上是 PRY)试图弄清楚类变量在 Ruby 中是如何工作的,我完全对我的发现感到困惑。

据我所见(如果我在这里错了请纠正我),类变量在类、这些类的实例、子类和子类的实例之间共享。但是,对于子类及其实例,如果类变量已在父类(super class)中分配,则类变量仅共享给父类(super class)。如果它没有在父类(super class)中分配给它,那么它在那里保持未定义,直到它被分配给,此时变量变得共享......到底是什么? (如果您感到困惑,请参阅下面的示例。)

这是为什么呢?我在某处听说 Ruby 类变量基于 Smalltalk 中的一些类似概念,但我真的很想知道为什么需要这种行为。


示例:

superfoo_and_subbar.rb 中:

class SuperFoo
def class_var_x=(x)
@@x = x
end
def class_var_x
@@x
end
end

class SubBar < SuperFoo
# Define these again, just in case they're bound at compile time or something...
def class_var_x=(x)
@@x = x
end
def class_var_x
@@x
end
end

PRY(或 IRB) session 中:

# Okay, let's do this!

require './superfoo_and_subbar' # => true

SuperFoo.new.class_var_x # NameError: uninitialized class variable @@x in SuperFoo
SubBar.new.class_var_x # NameError: uninitialized class variable @@x in SubBar

# Okay, no suprise there, let's define the class variable on SuperFoo
SuperFoo.new.class_var_x = 1
SuperFoo.new.class_var_x # => 1

# Okay, looks about right. What does bar say now?

SubBar.new.class_var_x # => 1

# Okay, that's pretty weird but I did hear that Ruby class variables behave
# that way, so no big deal.

SubBar.new.class_var_x = 2
SubBar.new.class_var_x # => 2
SuperFoo.new.class_var_x # => 2

# Right, so these both point to the same variable then.

新的 PRY session :

# Now let's try this again:

require './superfoo_and_subbar' # => true

SuperFoo.new.class_var_x # NameError: uninitialized class variable @@x in SuperFoo
SubBar.new.class_var_x # NameError: uninitialized class variable @@x in SubBar

# So far so good. Let's set x on SubBar first this time

SubBar.new.class_var_x = 2
SubBar.new.class_var_x # => 2

# Okay, so x is now set on SubBar so it should also be set on SuperFoo then, right?

SuperFoo.new.class_var_x # NameError: uninitialized class variable @@x in SuperFoo

# Wait, what? So they're seperate variables now?

SubBar.new.class_var_x # => 2
SuperFoo.new.class_var_x # NameError: uninitialized class variable @@x in SuperFoo

# It certainly looks that way. What happens if I set x on SuperFoo then?

SuperFoo.new.class_var_x = 3

SuperFoo.new.class_var_x # => 3
SubBar.new.class_var_x # => 3

# Wait, so now they're the same varaible again? What the heck?

SubBar.new.class_var_x = 4

SuperFoo.new.class_var_x # => 4
SubBar.new.class_var_x # => 4

# ...WHY!?!? Seriously, what's the point of this?

最佳答案

这就是继承的原理。是的,一旦父类(super class)定义它,类变量就会共享给它的子类。 SubBar.new.class_var_x 仅在类 SubBar 中创建了类变量。因此很明显,它的父类(super class)将无法访问它。

class Foo
def x_class_var=(val)
@@x =val
end
def x_class_var
@@x
end
end

class Bar<Foo
def x_class_var=(val)
@@x =val
end
def x_class_var
@@x
end
end

Foo.class_variables # => []
Bar.class_variables # => []
Bar.new.x_class_var = 10
Foo.class_variables # => []
Bar.class_variables # => [:@@x]

Bar.new.x_class_varBar 类中创建了类变量 @@xFoo作为 Bar 的父类(super class)将无法访问此 @@x 。现在换个方式看——

Foo.class_variables # => []
Bar.class_variables # => []
Foo.new.x_class_var = 10
Foo.class_variables # => [:@@x]
Bar.class_variables # => [:@@x]

现在 @@x 是在 Foo 类中创建的,因此作为 Foo 的子类,Bar 可以访问到 @@x。这是因为类变量可从父类(super class)共享到子类,而不是从子类到父类(super class),如我在上面的示例中所示。

关于ruby - 为什么 Ruby 类变量的行为如此奇怪?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20912146/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com