ruby中各种变量范围之间的区别

Posted

技术标签:

【中文标题】ruby中各种变量范围之间的区别【英文标题】:Difference between various variables scopes in ruby 【发布时间】:2012-07-15 19:51:17 【问题描述】:

Ruby 有 5 个变量范围:

    局部变量:这些是普通变量,例如x = 25y = gaurish 其中xy 是局部变量。 实例变量:在实际变量名前用@ 符号表示。主要与类一起使用,以便类的每个实例/对象具有不同/单独的值。例子。 @employee.name = 'Alex' 类变量:在变量名前用@@ 符号表示。类变量,我认为所有实例/对象具有相同的值。 全局变量:它们以$ 符号开头,任何地方都可以访问。例如$LOAD_PATH 常量:必须以大写字母开头,但按照约定写成ALL_CAPS。虽然,它是一个常量,但它的值不是常量,可以更改(不过,ruby 会抛出警告)。所以从某种意义上说,这也像一个变量。

您可能会注意到,以上所有变量都是存储某种类型的值的变量,并且它们的值可以更改。但是,每个范围都有一些不同。拥有 5 种不同类型的变量范围让我很困惑。主要是,我很难决定在什么情况下,我应该在我的代码中使用特定的范围。所以我有一些疑问。请回答:

    我注意到局部变量和类变量对于所有对象/实例都保持不变,这与实例变量不同。那么局部变量和类变量有什么区别呢? 可以使用局部变量代替类变量吗?或相反亦然。如果是,那为什么,如果不是,那为什么不呢? ruby 中的全局变量让我想起了 php 中邪恶的 global $x 变量。 ruby 中的全局变量是否也被认为是邪恶的,因此不应使用。或者,在某些特定情况下,在 ruby​​ 中使用全局变量是有意义的? 为什么常量不是常量并允许更改它们的值?根据定义,常量的值应该是常量,对吗?否则,我们可以只使用另一个变量而不改变它的值。这是否等同于 ruby​​ 中的 CONSTANT? 任何页面/资源/链接可以解释 ruby​​ 中 5​​ 个不同变量范围之间的区别?我喜欢保留一个方便参考。 在什么用例下,我应该在我的代码中使用特定的变量范围。所以可以用很酷的例子来解释所有 5 种情况,这是我感到困惑的主要原因。 在java中有没有像public这样的事实上的选择? 大多数用例中哪个是安全的选择?

感谢您花时间阅读和回答问题

【问题讨论】:

第一点,所有对象共享类级变量,每个单独的对象都有自己的局部变量副本 如果每个单独的对象都有自己的局部变量副本,那么局部变量不是更像实例变量吗? 有点,我想你可以这样看。实例变量属于对象的一个​​实例,通常构成该对象的属性。例如Person 对象可能有两个实例变量@first_name@last_name,它也可能有一个局部变量xxPerson 对象的状态无关 【参考方案1】:

    类变量对于所有实例都是相同的,因为它们是类变量——与类相关联。一切都访问同一个变量,包括每个实例。

    没有。局部变量就是局部变量。它们可能是函数的局部变量,或者是 类声明 的局部变量,这与作为类变量不同。当类声明结束时,类声明中的局部变量超出范围。

    这是因为它们完全相同——它们是全球性的。全局状态总是是邪恶的;这不是语言或环境的属性。也就是说,可能需要一些全局状态——就是这样。当有全局状态时使用全局状态是有意义的。诀窍是正确使用全局状态,这有时是一项不平凡的工作。

    Ruby 就是这样。

    克里斯已经给了一个。

    我会认为这个问题在很大程度上是自我回答的。当整个世界都需要访问时,全球化。特定于类实例时的实例。仅在本地范围内需要时为本地(例如,方法、块(注意 1.8 和 1.9 之间关于块范围的差异)等)当变量不应该更改时为常量。类变量,当它是每个实例都需要的东西,或者如果通过类方法公开,与类紧密相关的东西。

    没有“大多数用例”,这完全取决于您对变量所做的工作。而public 并不是Java 中事实上的选择——它取决于所讨论的实体。默认 Java 范围是包私有的(方法、属性)。在 Ruby 中使用哪个完全取决于用例,请注意,与 Java 一样,在 Ruby 中更容易,可以规避一些事情。

【讨论】:

【参考方案2】:

局部变量不等同于类变量,它们与您所在的块相关联。在块中声明的任何局部变量都可以在那里使用。类变量与您所在的类结构相关联。定义一个类本身就是一个块,因此您可能能够类似地访问局部变量,但您会发现如果您在不同的上下文中引用您的类,您将无法引用以相同方式的局部变量。

如果被滥用,全局变量会被认为是错误的形式。 OOP 应该帮助您构建程序,从而不需要整个程序的常量。把它们想象成实际上是全球性的:如果你不能保证它对整个世界的一致性,比如 PI 的价值或者你是否爱你的妻子,你可能不应该做出承诺。

一旦你掌握了它们,我发现“Ruby Variable Scope”是一个很好的参考。

【讨论】:

【参考方案3】:

我在以下链接中找到了关于 Ruby 中不同范围及其可见性的良好而深入的解释。Scopes and Visibilities with Examples in detail.

据此,

Class variable (@@a_variable): Available from the class definition and any sub-classes. Not available from anywhere outside.

Instance variable (@a_variable): Available only within a specific object, across all methods in a class instance. Not available directly from class definitions.

Global variable ($a_variable): Available everywhere within your Ruby script.

Local variable (a_variable): It is available only in the particular method or block in ruby script. 

关于实例变量的更多解释是:您可以在该特定类的任何方法中访问实例变量。虽然不能在方法之外访问局部变量。下面是一个来自 ruby​​ 僧侣的例子,它彻底解释了这个概念。

class Item

   def initialize(item_name, quantity)

       @item_name = item_name   
       @quantity = quantity

   end

  def show

   puts @item_name
   puts @quantity
   supplier = "Acme corp"
   puts supplier

  end
end

 Item.new("tv",1).show

这里的supplier是一个局部变量,在我们的例子中只能通过show方法访问。尝试在initialize方法中声明supplier变量,并在show方法中打印出来。作为未定义的变量供应商,它会报错。

我希望它有所帮助。 :)

【讨论】:

【参考方案4】:

这是我的两分钱,是为 c++/java/c# 程序员写的:

Ruby 本地/$Global 变量有点像 c++/java/c# 的本地/全局变量。

Ruby @instance 变量就像 c++/java/c# 的成员变量 /class 属性,可以在任何成员函数/类方法中访问。尽管 Ruby 实例不仅可以应用于类,还可以应用于 Ruby 模块。

Ruby @@class 变量就像 c++/java 的静态成员变量一样,在同一类的所有实例之间共享。

【讨论】:

以上是关于ruby中各种变量范围之间的区别的主要内容,如果未能解决你的问题,请参考以下文章

float和int有啥区别?

为啥C语言中float型变量的数据范围比int大

将字典加载到本地范围的方法之间的差异[重复]

UAA中范围和权限之间的区别

Clear-Variable 和将变量设置为 NULL 之间的区别

Javascript中变量声明语法(包括全局变量)之间的区别?