我的想法是为来自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 #<Test:0x000000017d9348 @ins="wtf?">
我们试图通过一个对象调用一个类方法,这个方法属于类,所以我们得到NoMethodError
[16] pry(main)> Test.ins
gah
我们正在调用一个类方法,因此它可以正确地看到类对象的实例变量。
[17] pry(main)> Test.ins2
NoMethodError: undefined method `ins2' for Test:Class
我们正在调用一个不正确的类的对象方法,因此抛出NoMethodError
。
以上所有都是用ruby 2.0进行的。那我在问什么呢?
答案 0 :(得分:9)
我发现
@variable
可能意味着两件非常不同的事情,这让我非常困惑。
不,它没有。类就像任何其他对象一样是对象。它们可以像任何其他对象一样拥有实例变量。它们可以像任何其他对象一样拥有实例方法。事实上,与Java不同,它有三种不同的“方法”(实例方法,静态方法和构造函数),在Ruby中,只有一种方法:实例方法。
将类作为对象的美妙之处恰恰在于@variable
总是意味着完全相同的事情。
没有类实例变量这样的东西:它只是一个普通的实例变量,就像任何其他变量一样。该对象恰好是Class
的实例,但这不会改变实例变量的性质。类String
的对象的实例变量不是字符串实例变量,它只是一个实例变量。同样,类Class
的对象的实例变量只是一个实例变量。
没有类方法这样的东西:它只是一个对象的普通单例方法,恰好是Class
的一个实例。 (另外,也没有单例方法这样的东西:它只是对象单例类的普通实例方法。)
注意:Rubyists可以在随意对话中使用术语“类方法”。但这并不意味着类方法实际存在,它只意味着“类对象的单例类的实例方法”是满口的。重要的是:因为类是对象,所以它们与所有其他对象一样完全。他们可以拥有实例方法(在课程Class
中定义,或者从Module
,Object
,Kernel
或BasicObject
继承),他们可以使用“单例方法”(它们实际上是各自单例类的实例方法),它们可以有实例变量。
他们也可以拥有类变量(@@variables
)......这些都很奇怪。忽略它们: - )
答案 1 :(得分:3)
首先,要了解实例变量,需要知道这一点 - 类是对象。
所有类都是Class
的实例(阅读文档),它继承自Object
。这就是为什么类是对象。
然后,每个实例变量(标有@
的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
答案 2 :(得分:0)
一切看起来都对我不错。
类变量将通过继承向下传递,而类上的实例变量则不会。 (src:Ruby class instance variable vs. class variable)
就设计而言,我倾向于完全避免使用类变量(我宁愿使用单例),但如果我必须选择一个,我可能会在类实例变量上选择一个类变量来避免混淆。