我知道类中的实例变量可以通过在变量名前加上 @ 符号来表示。在类中有一些实际应用@@variable 在 Ruby 中是什么意思?
在函数内部执行此操作的实际应用是什么?
def foo
one = 1
@two = 2
end
我知道类中的实例变量可以通过在变量名前加上 @ 符号来表示。在类中有一些实际应用@@variable 在 Ruby 中是什么意思?
在函数内部执行此操作的实际应用是什么?
def foo
one = 1
@two = 2
end
那是一个实例变量。它的价值在一个实例上持续存在。
class Foo
def set_baz
@baz = 1
end
def get_baz
@baz
end
end
foo = Foo.new
foo.get_baz #=> nil
foo.set_baz
foo.get_baz #=> 1
foo2 = Foo.new
foo.get_baz #=> nil
如您所见,我们可以@baz
在任何方法中进行设置,并且它会在实例上更新,我们可以稍后在其中获取它。
@
前缀设置并获取实例变量 on ,self
不管self
是什么。假设我启动了irb
,nowself
是为运行代码而创建的对象上下文。当您使用自己的代码创建自己的类时,self
(又名上下文)的值将在整个应用程序的各种方法中发生变化。
2.0.0-p0 :001 > @foo = 123
=> 123
2.0.0-p0 :002 > self.instance_variable_get :@foo
=> 123
2.0.0-p0 :003 > self
=> main
2.0.0-p0 :004 > self.class
=> Object
但实际上,除非您在课堂上,否则我不会设置实例变量。你只会让自己感到困惑,并且没有真正的理由这样做。
我想说,根据经验,如果您不确切知道一行代码中的内容,self
则根本不应该在其上设置实例变量。
您的问题表明您可能@
对@@
. 前者与类的特定实例相关联;后者由类的所有对象共享。扩展亚历克斯的答案:
class Foo
def set_baz(n)
@baz = n
end
def set_zoo(n)
@@zoo = n
end
def get_baz
@baz
end
def get_zoo
@@zoo
end
end
foo = Foo.new
bar = Foo.new
foo.set_baz(1)
foo.get_baz # 1
bar.set_baz(2)
bar.get_baz # 2
foo.get_baz # still 1
foo.set_zoo(3)
foo.get_zoo # 3
bar.set_zoo(4)
bar.get_zoo # 4
foo.get_zoo # also 4
在函数方法中执行此操作的实际应用是什么?
class Dog
def foo
one = 1
@two = 2
end
def bar
puts @two
puts one
end
end
d = Dog.new
d.foo
d.bar
--output:--
2
1.rb:9:in `bar': undefined local variable or method `one' for #<Dog:0x00000101086810 @two=2> (NameError)
from 1.rb:16:in `<main>'
局部变量,即前面没有 @ 的变量,在方法执行完成时被销毁。
是的 - 但这在常规函数中意味着什么,而不是类的方法?
实例变量,在它们前面有一个 @ 的那些,在它们被创建时将它们自己附加到任何对象自身:
def do_stuff
puts self #=>main
@val = 10
end
do_stuff
puts self #=>main
该输出有点不寻常,因为 self 等于main
在 def 内部和 def 外部调用的对象。通常一个 def 会改变 self--但是当 def 处于顶层时,一个 def 不会改变 self。
好的,所以如果 @val 附加到一个名为 main 的对象,并且 self=main,让我们打印出 @val:
def do_stuff
puts self #=>main
@val = 10
end
do_stuff
puts self.val #`<main>': undefined method `val' for main:Object (NoMethodError)
啊,是的。默认情况下,所有实例变量都是私有的,所以让我们在 main 的类中编写一些访问器:
def do_stuff
puts self #=>main
@val = 10
end
do_stuff
puts self.class #=>Object
class Object
attr_reader :val
end
puts self.val #=>10
接下来,在创建 def 时,def 将附加到当前类的任何内容。当前类或者等于self,或者如果self不是一个类,那么当前类就是self的类。在上面的例子中,当 do_stuff 被创建时 self=main:
puts self #main
def do_stuff
puts self
@val = 10
end
因为self不是类,所以当前类是self的类,我们可以看到是Object:
puts self.class #Object
所以 do_stuff 将自己附加到 Object 类,这意味着它成为 Object 类的实例方法。并且对于额外的点 - 它实际上成为一个私有实例方法:
puts Object.private_methods.grep(/^do/) #=>do_stuff
类内部的 defs 也将自己附加到当前类:
class Dog
puts self #=>Dog
def bark
puts "Woof"
end
end
...但与顶层不同,defs 成为类的公共实例方法。