Ruby 在函数中使用@符号作为变量前缀的目的是什么?

Ruby 在函数中使用@符号作为变量前缀的目的是什么?,ruby,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

我知道类中的实例变量可以通过在变量名前面加@符号来表示。这在课堂上有一些实际应用

在函数中这样做的实际应用是什么

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
,并在实例中更新它,稍后我们可以在实例中获取它


@
前缀设置并获取
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是什么,你根本不应该在它上面设置实例变量。

这是一个实例变量。它的值在实例上保持不变

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
是什么,你根本不应该在上面设置实例变量。

你的问题表明你可能把
@
@
搞混了。前者与类的特定实例相关联;后者由类的所有对象共享。要详细介绍Alex的答案:

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

您的问题表明您可能将
@
@
混淆。前者与类的特定实例相关联;后者由类的所有对象共享。要详细介绍Alex的答案:

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
在函数方法中这样做的实际应用是什么

该输出有点不寻常,因为self在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)
接下来,在创建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将自身附加到对象类,这意味着它将成为对象类的实例方法。另外,它实际上变成了一个私有实例方法:

puts Object.private_methods.grep(/^do/)   #=>do_stuff
类内的DEF也将自身附加到当前类:

class Dog
  puts self   #=>Dog

  def bark
    puts "Woof"
  end
end
…但与顶层不同,def成为类的公共实例方法

在函数方法中这样做的实际应用是什么

该输出有点不寻常,因为self在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)
接下来,在创建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将自身附加到对象类,这意味着它将成为对象类的实例方法。另外,它实际上变成了一个私有实例方法:

puts Object.private_methods.grep(/^do/)   #=>do_stuff
类内的DEF也将自身附加到当前类:

class Dog
  puts self   #=>Dog

  def bark
    puts "Woof"
  end
end

…但与顶层不同,DEF成为类的公共实例方法。

是-但这在常规函数中意味着什么,而不是类的方法?它是当前任何
self
上的实例变量。这很可能是
内核的全局单例实例(我想…)一切都是ruby中某个东西的实例,不管你意识到与否,你都在进行基于类的编程。ruby中没有“常规函数”这样的东西。一切都是某处某个对象上的方法。但是,实际上,如果只使用默认对象,则存储在
@
变量中的任何内容都会在调用之间保持不变,并且对于从相同上下文调用的其他函数也是可见的。当函数返回时,没有
@
的变量将消失。@user784637请参阅我的编辑,这解释了实例变量在没有任何显式类的情况下的行为。此处拼写cop,wether!=不管你是否意识到,你都会看到为什么你可能想在你的评论中使用它。是的-但这在一个常规函数中意味着什么,而不是一个类的方法?它是一个实例变量,在当前我使用的
self