ruby:类实例变量vs实例变量
我的想法是为来自java
背景的人创建一个社区wiki,因为阅读了很多解释,直到我真正尝试了几件事并且拼图的各个部分开始找到他们的位置时,我无法理解任何事情。 但我首先需要确保我做对了。 从这样的背景来看,我发现@variable
可能意味着两个非常不同的东西,这让我非常困惑。 这是一个例子:
class Test @ins = "gah" def self.ins puts @ins end def initialize() @ins = "wtf?" end def ins2 puts @ins end end
据我所知,第一个@ins
是表示类Test
的对象的实例变量。 第二个@ins
是Test
类对象中的实例变量。
现在事情开始对我有意义了。 这里有几个例子:
[14] pry(main)> test.ins2 wtf?
我们正在调用一个对象的方法,它返回对象的实例变量。
[15] pry(main)> test.ins NoMethodError: undefined method `ins' for #
我们试图通过一个对象调用一个类方法,这个方法属于类,所以我们得到NoMethodError
[16] pry(main)> Test.ins gah
我们正在调用一个类方法,因此它可以正确地看到类对象的实例变量。
[17] pry(main)> Test.ins2 NoMethodError: undefined method `ins2' for Test:Class
我们通过不正确的类调用一个对象方法,因此抛出NoMethodError
。
以上所有都是用ruby 2.0进行的。 那么我问的是什么?
- 我做对了吗?
- 我的ruby术语是否正确?
- 在正确设计的应用程序中有意义的类实例变量的任何实际用法? 或者这些只是更好的@@类变量?
我发现
@variable
可能意味着两个非常不同的东西,这让我非常困惑。
不,它没有。 类就像任何其他对象一样是对象。 它们可以像任何其他对象一样拥有实例变量。 它们可以像任何其他对象一样拥有实例方法。 实际上,与Java不同,它有三种不同的“方法”(实例方法,静态方法和构造函数),在Ruby中,只有一种方法:实例方法。
将类作为对象的美妙之处正是@variable
总是意味着完全相同的东西 。
没有类实例变量这样的东西:它只是一个普通的实例变量,就像任何其他变量一样。 该对象恰好是Class
一个实例,但这不会改变实例变量的性质。 String
类对象的实例变量不是字符串实例变量,它只是一个实例变量。 同样, Class
对象的实例变量只是一个实例变量。
没有类方法这样的东西:它只是一个对象的普通单例方法,恰好是Class
一个实例。 (实际上,也没有单例方法这样的东西:它只是对象的单例类的普通实例方法。)
注意:Rubyists可以在随意对话中使用术语“类方法”。 但这并不意味着类方法实际存在,它只意味着“类对象的单例类的实例方法”是满口的。 重要的是:因为类是对象,它们的工作方式与所有其他对象完全相同 。 它们可以有实例方法(在类Class
定义或从Module
, Object
, Kernel
或BasicObject
),它们可以有“单例方法”(它们实际上是它们各自的单例类的实例方法),它们可以有实例变量。
他们也可以有类变量( @@variables
)……这些都很奇怪。 别理他们 :-)
-
首先,要理解实例变量 ,需要知道这一点 – 类是对象 。
所有类都是inheritance自
Object
的Class
(读取doc)的实例。 这就是类是对象的原因。 -
然后,每个实例变量(标记为
@
ID,如@ins
)都在self
中定义。当
self
是一个类时,它们是类的实例变量(类实例变量)。 当self
是一个对象时,它们是对象的实例变量(实例变量)。 -
在不同的代码范围中,
self
代表不同的东西。class Test # class scope, uncomment following line to see the value of self # p self @ins = "gah" def self.ins # class scope # p self puts @ins end def initialize() # object scope # p self @ins = "wtf?" end def ins2 # object scope # p self puts @ins end end
一切看起来都对我好。
类变量将通过inheritance向下传递,而类上的实例变量则不会。 (src: Ruby类实例变量与类变量 )
就设计而言,我倾向于完全避免使用类变量(我宁愿使用单例),但如果我必须选择一个,我可能会在类实例变量上选择一个类变量来避免混淆。