1

我知道类中的实例变量可以通过在变量名前加上 @ 符号来表示。在类中有一些实际应用@@variable 在 Ruby 中是什么意思?

在函数内部执行此操作的实际应用是什么?

def foo
    one = 1
    @two = 2
end
4

3 回答 3

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在任何方法中进行设置,并且它会在实例上更新,我们可以稍后在其中获取它。


@前缀设置并获取实例变量 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 根本不应该在其上设置实例变量。

于 2013-08-13T22:26:37.480 回答
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
于 2013-08-13T22:30:49.360 回答
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 等于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 成为类的公共实例方法。

于 2013-08-14T03:49:44.143 回答