Ruby类变量与Java静态变量类似吗?
我正在从Java过渡到Ruby,并试图理解Ruby的作用域Ruby类变量与Java静态变量类似吗?,java,ruby,Java,Ruby,我正在从Java过渡到Ruby,并试图理解Ruby的作用域 类变量的行为似乎与Java中的静态变量相同。这个解释正确吗?如果是这样,那么Ruby全局变量是否等同于Java中的公共静态变量?我不熟悉Java,但我可以用Ruby术语解释 在Ruby中,类变量在变量名之前有@。它的行为不像你认为的那样。创建类变量后,它将在所有子类之间共享。它不限于您在其中创建它的类 对于全局变量,在变量名之前有$。它做的和听起来完全一样,它是全球性的,可以在任何地方访问 Ruby中不建议使用这两个变量。您可以使用实例
类变量的行为似乎与Java中的静态变量相同。这个解释正确吗?如果是这样,那么Ruby全局变量是否等同于Java中的公共静态变量?我不熟悉Java,但我可以用Ruby术语解释 在Ruby中,类变量在变量名之前有
@
。它的行为不像你认为的那样。创建类变量后,它将在所有子类之间共享。它不限于您在其中创建它的类
对于全局变量,在变量名之前有$
。它做的和听起来完全一样,它是全球性的,可以在任何地方访问
Ruby中不建议使用这两个变量。您可以使用实例变量执行所需操作,该变量在名称前有@
。它是特定于对象的。如果在一个对象中声明它,它将不会在另一个对象中显示
我希望这事能澄清 由于Ruby和Java是面向对象的,它们之间有很多相似之处,但它们的族谱是不同的。Ruby非常依赖Java,而Java继承了思维学派的思想 这里的区别在于Ruby的public/private/protected的概念要弱得多,它们更多的是建议而不是规则,静态方法或常量之类的东西在语言中更像是一种模式而不是一种构造 全局变量非常不受欢迎,如果随意使用,它们会导致混乱。Ruby的方法是命名事物的名称空间:
$ugly_global = 0 # Not recommended, could conflict with other code
# Ownership of this variable isn't made clear.
$ugly_global += 1 # Works, but again, it's without context.
module UglyCounter # Defines a module/namespace to live in
def self.current # Defines a clear interface to this value
@counter ||= 0 # Initializes a local instance variable
end
def self.current=(v) # Allow modification of this value
@counter = v.to_i # A chance to perform any casting/cleaning
end
end
UglyCounter.current += 1 # Modifies the state of a variable, but
# the context is made clear.
即使是像这个模块这样的薄层也能让您截获来自这个变量的读/写操作并改变其行为。也许您希望默认为特定值,或者将值转换为规范化形式。对于一个简单的全局代码,您必须在任何地方重复此代码。在这里你可以巩固它
类变量是完全不同的事情。它们也是最好避免的,因为在类和此类实例之间共享数据可能会很混乱。这是两种不同的情况,应该尊重分离
class MessyClass
@@shared = 0
def counter
@@shared
end
def counter=(v)
@@shared = v
end
end
对于如何使用共享类级实例变量,这是一个相当粗略的理解。这里的问题是,每个实例都在直接修改它,绕过类上下文,这意味着该类无能为力。这从根本上讲是不礼貌的,因为该实例过度扩展了其权限。更好的方法是:
class CleanerClass
def self.counter
@counter ||= 0
end
def self.counter=(v)
@counter = v.to_i
end
# These are reduced to simple bridge methods, nothing more. Because
# they simply forward calls there's no breach of authority.
def counter
self.class.counter
end
def counter=(v)
self.class.counter = v
end
end
在许多语言中,静态类方法在实例范围内自动可用,但在Ruby中并非如此。您必须编写桥接/代理/委托方法,这里的术语根据您的习惯而有所不同。一个重要的区别是类方法和实例变量在Ruby中的交互方式,而静态方法和实例变量在Java中是无法实现的 塔德曼的答案包含以下代码:
class CleanerClass
def self.counter
@counter ||= 0
end
def self.counter=(v)
@counter = v.to_i
end
end
对于全世界的Java(和C#)程序员来说,这段代码似乎不应该工作。毕竟,在该模型中,从静态方法访问实例变量的想法是不一致的(甚至不会编译)。关键是你没有一个实例
然而,在Ruby中,每个类定义本身都是
类
类型的实例。对@counter
的引用实际上在定义CleanerClass
的类
对象上创建了一个实例变量。将其更改为@@counter
,这似乎是您应该做的,它将污染除您声明它的类之外的其他类。我不熟悉Java,但找到了答案,希望对您有所帮助!一句忠告:在你所知道的一种语言和你正在学习的一种语言之间寻找相似之处可能是一条死胡同,通常会导致在一种新的语言中出现一段不惯用、难看的代码。我更愿意关注特定的问题,以及如何用不同的语言解决它们。选择一个在Java中通常使用静态变量解决的问题,然后询问Ruby中解决该问题的正确方法是什么。答案可能是类变量,但更常见的是一些显然无关的东西。不,但我也有同样的错误直觉,所以我感觉到了你。@MladenJablanović我认为你将把以前的直觉带入一门新的语言是不可避免的,虽然这会让你误入歧途,但在大多数情况下,这也会节省你很多时间。@Casey:同意,我只是说,当你问一个问题(关于某某或其他方面)时,最好从“我如何在这里解决这个问题”开始,而不是“我如何在这里使用语言和功能”。我想这是一种XY问题。还值得一提的是self
值的差异。这一点很好self
始终是您所处的环境,除非您特意重新绑定,所以也存在这样的情况。好吧,类变量的大问题不是在实例之间共享太多信息(毕竟,类方法并不能解决它)但是,我还要提到,IVAR也可以设置在类对象上。全局变量确实是可以避免的,但当状态在类及其子类的实例之间共享时,类变量是一个非常合适的解决方案。