题
我有一个程序看起来像:
$offset = Point.new(100, 200);
def draw(point)
pointNew = $offset + point;
drawAbsolute(point)
end
draw(Point.new(3, 4));
使用 $offset
似乎有点怪异。
在C,如果我定义的东西之外的任何功能,它是一个全球性的变动。为什么在红宝石它必须是 $offset
但是不能 offset
并且仍然是全球?如果它是 offset
, 然后这是一个地方?但是,地方,在那里,因为这感觉很多全球性的。
是否有更好的方式来编写上述代码?使用 $offset
可能看起来有点丑,在第一次。
更新:我可以把这种偏内 class
定义,但是如果两个或几类需要用这个不变?在这种情况下我还是需要定义一个 $offset
?
解决方案
有一件事你需要知道的是在红宝石的一切是一个对象。有鉴于此,如果你不定你的内的方法 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)
希望澄清这一点。
其他提示
变量范围在红宝石的控制是通过印记到某一程度。变量开始 $
是全球性的,变量 @
实例的变量, @@
装置类变量和名称开始一个资本函是常数。所有其他变量的当地人。当你打开一类或方法,这是一个新范围,以及当地可用的以前的范围不可用。
我通常更倾向于避免造成全球变量。有两种技术通常实现同样的目的,我考虑清洁:
创建一个恒定在一个模块。因此,在这种情况下,你会把所有这类需要的偏移的模块
Foo
并创建一个常数Offset
, 那所有的课程可以访问Foo::Offset
.定义的方法访问的价值。你可以定义的方法在全球范围内,但同样,我认为这是更好地封装它在一个模块或课。这种方式的数据可在那里你需要它,你甚至可以改变它,如果你需要,但结构的程序和所有权的数据将能更加清晰。这更加符合OO设计原则。
其中一个原因为什么全球变需要一种前缀(的 $
)是因为在红宝石,不同于在C,你不必声明变量之前分配给他们,所以没有一个具体的前缀为globals给出这样的声明 offset = Point.new(100, 200)
在你的绘制方法,然后红宝石也不知道如果你指的是现有的可变或者创建一个新的地方变量内的方法。相同的 @
前缀为实例的变量。
我认为这是本地的文件宣布抵消。考虑每一个文件是一种方法本身。
也许把整个事情变成一类,然后使偏移的一个类变量 @@offset = Point.new(100, 200);
?