ruby:类实例变量vs实例变量

时间:2014-07-29 21:23:58

标签: ruby instance-variables class-instance-variables

我的想法是为来自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进行的。那我在问什么呢?

  • 我说得对吗?
  • 我的红宝石术语是否正确?
  • 在正确设计的应用程序中有意义的类实例变量的任何实际用法?或者这些是更好的@@类变量?

3 个答案:

答案 0 :(得分:9)

  

我发现@variable可能意味着两件非常不同的事情,这让我非常困惑。

不,它没有。类就像任何其他对象一样是对象。它们可以像任何其他对象一样拥有实例变量。它们可以像任何其他对象一样拥有实例方法。事实上,与Java不同,它有三种不同的“方法”(实例方法,静态方法和构造函数),在Ruby中,只有一种方法:实例方法。

将类作为对象的美妙之处恰恰在于@variable总是意味着完全相同的事情

没有类实例变量这样的东西:它只是一个普通的实例变量,就像任何其他变量一样。该对象恰好是Class的实例,但这不会改变实例变量的性质。类String的对象的实例变量不是字符串实例变量,它只是一个实例变量。同样,类Class的对象的实例变量只是一个实例变量。

没有类方法这样的东西:它只是一个对象的普通单例方法,恰好是Class的一个实例。 (另外,也没有单例方法这样的东西:它只是对象单例类的普通实例方法。)

注意:Rubyists可以在随意对话中使用术语“类方法”。但这并不意味着类方法实际存在,它只意味着“类对象的单例类的实例方法”是满口的。重要的是:因为类是对象,所以它们与所有其他对象一样完全。他们可以拥有实例方法(在课程Class中定义,或者从ModuleObjectKernelBasicObject继承),他们可以使用“单例方法”(它们实际上是各自单例类的实例方法),它们可以有实例变量。

他们也可以拥有类变量(@@variables)......这些都很奇怪。忽略它们: - )

答案 1 :(得分:3)

  1. 首先,要了解实例变量,需要知道这一点 - 类是对象

    所有类都是Class的实例(阅读文档),它继承自Object。这就是为什么类是对象

  2. 然后,每个实例变量(标有@的ID,如@ins)都在self中定义。

    self是一个类时,它们是类的实例变量(类实例变量)。 当self是对象时,它们是对象的实例变量(实例变量)。

  3. 在不同的代码范围中,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

就设计而言,我倾向于完全避免使用类变量(我宁愿使用单例),但如果我必须选择一个,我可能会在类实例变量上选择一个类变量来避免混淆。