I have a program that looks like:
我有一个程序是这样的:
$offset = Point.new(100, 200);
def draw(point)
pointNew = $offset + point;
drawAbsolute(point)
end
draw(Point.new(3, 4));
the use of $offset
seems a bit weird.
使用$offset似乎有点奇怪。
In C, if I define something outside of any function, it is a global variable automatically. Why in Ruby does it have to be $offset
but cannot be offset
and still be global? If it is offset
, then it is a local? But local to where, because it feels very much global.
在C语言中,如果我定义任何函数之外的东西,它将自动成为一个全局变量。为什么在Ruby中,它必须是$offset,但不能被抵消,并且仍然是全局的?如果它是偏移的,那么它是局部的?但当地,因为它感觉很全球化。
Are there better ways to write the code above? The use of $offset
may seem a bit ugly at first.
有更好的方法来编写上面的代码吗?$offset的使用乍一看可能有点难看。
Update: I can put this offset inside a class
definition, but what if two or several classes need to use this constant? In this case do I still need to define an $offset
?
更新:我可以将这个偏移量放在类定义中,但是如果两个或几个类需要使用这个常量呢?在这种情况下,我还需要定义一个$offset吗?
4 个解决方案
#1
53
One thing you need to realize is in Ruby everything is an object. Given that, if you don't define your methods within Module
or Class
, Ruby will put it within the Object
class. So, your code will be local to the Object
scope.
你需要意识到的是,在Ruby中,一切都是对象。因此,如果不在模块或类中定义方法,Ruby将把它放在对象类中。因此,您的代码将是对象范围的本地代码。
A typical approach on Object Oriented Programming is encapsulate all logic within a class:
面向对象编程的典型方法是将所有逻辑封装在一个类中:
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)
Hope this clarifies a bit.
希望这能澄清一点。
#2
107
Variable scope in Ruby is controlled by sigils to some degree. Variables starting with $
are global, variables with @
are instance variables, @@
means class variables, and names starting with a capital letter are constants. All other variables are locals. When you open a class or method, that's a new scope, and locals available in the previous scope aren't available.
Ruby中的变量作用域在一定程度上是由sigils控制的。以$开头的变量是全局变量,以@开头的变量是实例变量,@@表示类变量,以大写字母开头的名称是常量。所有其他变量都是局部变量。当您打开一个类或方法时,这是一个新的作用域,并且前面作用域中的局部变量不可用。
I generally prefer to avoid creating global variables. There are two techniques that generally achieve the same purpose that I consider cleaner:
我通常倾向于避免创建全局变量。有两种技术通常达到我认为比较干净的目的:
-
Create a constant in a module. So in this case, you would put all the classes that need the offset in the module
Foo
and create a constantOffset
, so then all the classes could accessFoo::Offset
.在模块中创建一个常量。因此,在这种情况下,您可以将需要在模块Foo中的偏移量的所有类都放入,并创建一个常量偏移量,因此,所有的类都可以访问Foo:: offset。
-
Define a method to access the value. You can define the method globally, but again, I think it's better to encapsulate it in a module or class. This way the data is available where you need it and you can even alter it if you need to, but the structure of your program and the ownership of the data will be clearer. This is more in line with OO design principles.
定义一个方法来访问该值。您可以全局地定义方法,但是我认为最好将它封装在模块或类中。通过这种方式,数据可以在需要的地方使用,甚至可以在需要的时候进行修改,但是程序的结构和数据的所有权将更加清晰。这更符合OO设计原则。
#3
9
One of the reasons why the global variable needs an prefix (the $
) is because in Ruby, unlike in C, you don't have to declare your variables before assigning to them so without a specific prefix for globals given a statement like offset = Point.new(100, 200)
inside your draw method then Ruby wouldn't know if you were referring to the existing variable or creating a new local variable inside your method. Same with the @
prefix for instance variables.
全局变量需要前缀($)的原因之一是,在Ruby中,与在C中不同,您不必在赋值给变量之前声明变量,因此在给定如offset = Point这样的语句的情况下,不需要为全局变量指定特定的前缀。在您的绘制方法中新建(100,200),然后Ruby不知道您是在引用现有变量,还是在方法中创建一个新的局部变量。与实例变量的@前缀相同。
#4
-2
I think it's local to the file you declared offset. Consider every file to be a method itself.
我认为它是本地的文件你声明的偏移。将每个文件都视为方法本身。
Maybe put the whole thing into a class and then make offset a class variable with @@offset = Point.new(100, 200);
?
可能将整个内容放到一个类中,然后使用@@offset = Point对类变量进行偏移。新(100、200);?
#1
53
One thing you need to realize is in Ruby everything is an object. Given that, if you don't define your methods within Module
or Class
, Ruby will put it within the Object
class. So, your code will be local to the Object
scope.
你需要意识到的是,在Ruby中,一切都是对象。因此,如果不在模块或类中定义方法,Ruby将把它放在对象类中。因此,您的代码将是对象范围的本地代码。
A typical approach on Object Oriented Programming is encapsulate all logic within a class:
面向对象编程的典型方法是将所有逻辑封装在一个类中:
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)
Hope this clarifies a bit.
希望这能澄清一点。
#2
107
Variable scope in Ruby is controlled by sigils to some degree. Variables starting with $
are global, variables with @
are instance variables, @@
means class variables, and names starting with a capital letter are constants. All other variables are locals. When you open a class or method, that's a new scope, and locals available in the previous scope aren't available.
Ruby中的变量作用域在一定程度上是由sigils控制的。以$开头的变量是全局变量,以@开头的变量是实例变量,@@表示类变量,以大写字母开头的名称是常量。所有其他变量都是局部变量。当您打开一个类或方法时,这是一个新的作用域,并且前面作用域中的局部变量不可用。
I generally prefer to avoid creating global variables. There are two techniques that generally achieve the same purpose that I consider cleaner:
我通常倾向于避免创建全局变量。有两种技术通常达到我认为比较干净的目的:
-
Create a constant in a module. So in this case, you would put all the classes that need the offset in the module
Foo
and create a constantOffset
, so then all the classes could accessFoo::Offset
.在模块中创建一个常量。因此,在这种情况下,您可以将需要在模块Foo中的偏移量的所有类都放入,并创建一个常量偏移量,因此,所有的类都可以访问Foo:: offset。
-
Define a method to access the value. You can define the method globally, but again, I think it's better to encapsulate it in a module or class. This way the data is available where you need it and you can even alter it if you need to, but the structure of your program and the ownership of the data will be clearer. This is more in line with OO design principles.
定义一个方法来访问该值。您可以全局地定义方法,但是我认为最好将它封装在模块或类中。通过这种方式,数据可以在需要的地方使用,甚至可以在需要的时候进行修改,但是程序的结构和数据的所有权将更加清晰。这更符合OO设计原则。
#3
9
One of the reasons why the global variable needs an prefix (the $
) is because in Ruby, unlike in C, you don't have to declare your variables before assigning to them so without a specific prefix for globals given a statement like offset = Point.new(100, 200)
inside your draw method then Ruby wouldn't know if you were referring to the existing variable or creating a new local variable inside your method. Same with the @
prefix for instance variables.
全局变量需要前缀($)的原因之一是,在Ruby中,与在C中不同,您不必在赋值给变量之前声明变量,因此在给定如offset = Point这样的语句的情况下,不需要为全局变量指定特定的前缀。在您的绘制方法中新建(100,200),然后Ruby不知道您是在引用现有变量,还是在方法中创建一个新的局部变量。与实例变量的@前缀相同。
#4
-2
I think it's local to the file you declared offset. Consider every file to be a method itself.
我认为它是本地的文件你声明的偏移。将每个文件都视为方法本身。
Maybe put the whole thing into a class and then make offset a class variable with @@offset = Point.new(100, 200);
?
可能将整个内容放到一个类中,然后使用@@offset = Point对类变量进行偏移。新(100、200);?