【问题标题】:How do you use global variables or constant values in Ruby?如何在 Ruby 中使用全局变量或常量值?
【发布时间】:2010-11-05 18:09:26
【问题描述】:

我有一个看起来像这样的程序:

$offset = Point.new(100, 200);

def draw(point)
  pointNew = $offset + point;
  drawAbsolute(point)
end

draw(Point.new(3, 4));

$offset 的使用似乎有点奇怪。

在 C 语言中,如果我在任何函数之外定义一些东西,它会自动成为一个全局变量。为什么在 Ruby 中它必须是 $offset 但不能是 offset 并且仍然是全局的?如果是offset,那么是本地的吗?但是本地到哪里,因为它感觉非常全球化。

有没有更好的方法来编写上面的代码? $offset 的使用一开始可能看起来有点难看。


更新:我可以将此偏移量放在class 定义中,但如果两个或多个类需要使用此常量怎么办?在这种情况下我还需要定义$offset吗?

【问题讨论】:

  • 来自 C 的您可能不知道这一点,但在 Ruby 中您不需要在行尾放置分号。你只需要使用 ;在同一行上分隔多个语句,例如"a = 5; b = 10"

标签: ruby global-variables


【解决方案1】:

全局变量需要前缀(称为“sigil”)的原因之一是因为在 Ruby 中,与 C 不同,您不必在分配变量之前声明变量。印记被用作明确变量范围的一种方式。

如果没有全局变量的特定前缀,则在 draw 方法中给定语句 pointNew = offset + point 然后 offset 指的是方法中的局部变量(在这种情况下会导致 NameError)。 @ 用于引用实例变量,@@ 用于引用类变量。

在其他使用显式声明的语言中,例如CJava 等。声明的位置用于控制范围。

【讨论】:

  • $ 如何帮助 Ruby 知道这是一个新变量还是一个现有变量?如果您为$foo 分配了一些东西,认为它是一些现有的$foo,但碰巧还没有任何$foo,或者有但有人删除了它,那么Ruby 将创建$foo 作为新的尽管如此,还是全球性的,尽管它与您想象的$foo 不同。 $ 不会修复缺少正确声明的问题。
【解决方案2】:

您需要意识到在 Ruby 中一切都是对象。鉴于此,如果您没有在ModuleClass 中定义您的方法,Ruby 会将其放在Object 类中。因此,您的代码将位于 Object 范围内。

面向对象编程的典型方法是将所有逻辑封装在一个类中:

class Point
  attr_accessor :x, :y

  # If we don't specify coordinates, we start at 0.
  def initialize(x = 0, y = 0)
    # Notice that `@` indicates instance variables.
    @x = x
    @y = y
  end

  # Here we override the `+' operator.
  def +(point)
    Point.new(self.x + point.x, self.y + point.y)
  end

  # Here we draw the point.
  def draw(offset = nil)
    if offset.nil?
      new_point = self
    else
      new_point = self + offset 
    end
    new_point.draw_absolute
  end

  def draw_absolute
    puts "x: #{self.x}, y: #{self.y}"
  end
end

first_point = Point.new(100, 200)
second_point = Point.new(3, 4)

second_point.draw(first_point)

希望这能澄清一点。

【讨论】:

  • +1 用于重构。关于顶级代码在 Object 范围内是本地的:对于没有 $ 前缀的变量来说,这是正确的,但相比之下,methods 你放在那里 are 全局(同时也成为Object 类的私有成员)。
  • 所以我认为,如果所有 Point 对象都相对于某个常量偏移量,那么我可以将偏移量 (x, y) 作为类常量,所以 @987654330 @ 将使用此类常量作为偏移量
【解决方案3】:

我认为它是您声明偏移量的文件的本地文件。将每个文件视为一个方法本身。

也许把整个东西放到一个类中,然后用@@offset = Point.new(100, 200);偏移一个类变量?

【讨论】:

  • 不,局部变量不是文件的本地变量,而是声明它的最里面的块。
【解决方案4】:

Ruby 中的变量范围在某种程度上由 sigils 控制。 $ 开头的变量是全局变量,@ 是实例变量,@@ 是类变量,以大写字母开头的名字是常量。所有其他变量都是本地变量。当您打开一个类或方法时,这是一个新的作用域,而在以前的作用域中可用的本地变量不可用。

我通常更喜欢避免创建全局变量。有两种技术通常可以达到我认为更清洁的相同目的:

  1. 在模块中创建一个常量。所以在这种情况下,你可以把所有需要偏移量的类放在模块Foo中,并创建一个常量Offset,这样所有的类就可以访问Foo::Offset

  2. 定义访问值的方法。您可以全局定义该方法,但同样,我认为最好将其封装在模块或类中。这样,数据就可以在您需要的地方使用,您甚至可以根据需要对其进行更改,但是您的程序结构和数据的所有权将更加清晰。这更符合OO设计原则。

【讨论】:

    猜你喜欢
    • 2012-06-09
    • 2018-05-20
    • 1970-01-01
    • 2011-01-22
    • 2013-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-30
    相关资源
    最近更新 更多