我理解类中的实例变量可以通过在变量名前加上@符号来表示。在类What does @@variable mean in Ruby?
中有一些实际应用在函数内部执行此操作的实际应用是什么?
def foo
one = 1
@two = 2
end
答案 0 :(得分:4)
这是实例变量。它的值在一个实例上持续存在。
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
,并在实例上更新,我们可以在以后获取它。
@
前缀设置并获取self
上的实例变量,无论self
是什么。假设我启动irb
,现在self
是为运行代码而创建的对象上下文。当您使用自己的代码创建自己的类时,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
是什么,你不应该设置实例变量它根本就没有。
答案 1 :(得分:0)
您的问题表明您可能会@
与@@
混淆。前者与某个类的特定实例相关联;后者由该类的所有对象共享。扩展亚历克斯的答案:
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
答案 2 :(得分:0)
在
函数方法中执行此操作的实际应用是什么?
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在def内部和def外部等于名为main
的对象。通常def会改变自我 - 但是当def处于顶层时def不会改变自我。
好的,如果@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成为该类的公共实例方法。