我的程序看起来像:
$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
?
答案 0 :(得分:110)
Ruby中的变量范围在某种程度上受到了sigils的控制。以$
开头的变量是全局变量,@
变量是实例变量,@@
表示类变量,以大写字母开头的名称是常量。所有其他变量都是本地变量。当您打开一个类或方法时,这是一个新的范围,并且前一个范围中可用的本地可用不可用。
我通常更愿意避免创建全局变量。有两种技术通常可以实现我认为更清洁的相同目的:
在模块中创建常量。因此,在这种情况下,您将所有需要偏移的类放在模块Foo
中并创建一个常量Offset
,这样所有类都可以访问Foo::Offset
。
定义访问该值的方法。您可以全局定义方法,但我认为最好将其封装在模块或类中。这样,您可以在需要的地方获得数据,如果需要,您甚至可以更改数据,但程序的结构和数据的所有权将更加清晰。这更符合OO设计原则。
答案 1 :(得分:53)
你需要意识到的一件事是在Ruby中,一切都是一个对象。鉴于此,如果您未在Module
或Class
中定义方法,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)
希望这有点澄清。
答案 2 :(得分:9)
全局变量需要前缀($
)的原因之一是因为在Ruby中,与C不同,在分配变量之前不必声明变量,因此没有特定的前缀globals在draw方法中给出了offset = Point.new(100, 200)
之类的语句,然后Ruby不知道你是在引用现有变量还是在方法中创建一个新的局部变量。与实例变量的@
前缀相同。
答案 3 :(得分:-2)
我认为它是您声明偏移的文件的本地。将每个文件视为一种方法本身。
也许将整个事物放入一个类中,然后使用@@offset = Point.new(100, 200);