首页 > 解决方案 > 类变量覆盖

问题描述

我在玩类变量,我知道我可以覆盖子类中的类变量,但我没有意识到我在哪里调用类方法很重要。例如;

class Vehicle
  @@wheels = 4

  def self.wheels
    @@wheels
  end
end

puts Vehicle.wheels #4
puts Vehicle.wheels #4
puts Vehicle.wheels #4

class Motorcycle < Vehicle
  @@wheels = 2
end

puts语句输出 4,这对我来说都是有意义的,因为我认为在从类@@wheels中实例化一个对象之前,您不会被覆盖。Motorcycle所以我这样做了:

class Vehicle
  @@wheels = 4

  def self.wheels
    @@wheels
  end
end

class Motorcycle < Vehicle
  @@wheels = 2
end

puts Vehicle.wheels #2
puts Vehicle.wheels #2
puts Vehicle.wheels #2

现在,一旦我将这三行移到类之后,Motorcycle它们就会输出 2 ......即使一个Motorcycle对象还没有被实例化。这让我很困惑。详细来说这里发生了什么?是因为当我们尝试访问它时加载了类变量吗?这怎么可能?

标签: rubyoopclass-variables

解决方案


首先,实例化与它无关;这是一个类变量,而不是实例变量。你的代码从不实例化任何东西;正如所写的那样,它也不需要。我们只是在谈论一些课程。但是类是 Ruby 中的一等对象,所以这很好。

其次,顺序很重要,因为在 Ruby 中所有语句都是可执行的。当你说

class Motorcycle < Vehicle
  @@wheels = 2
end

...所有这些代码现在都在执行,就在你说它的那一刻——当 Ruby 遵从指令走下页面时遇到它的那一刻。该代码不仅仅是未来某个时间要遵守的模板;它说:“创建一个摩托车类并将其类变量设置wheels2, now。”

第三,你没有“压倒”任何东西。在 Motorcycle类中,与您之前@@wheels @@wheelsVehicle 定义的类变量完全相同。“覆盖”它的不是其他变量。这是一个单一的值,其工作方式类似于一种命名空间全局,可从类、任何子类及其任何实例访问。

有关更多信息,请参阅(例如):

如果你想要一些你可以覆盖的东西,你正在寻找的可能更像是类上下文中的一个实例变量,通常称为“类实例变量”——例如:

class Vehicle
  @wheels = 4
  class << self
    attr_reader :wheels
  end
end

class Motorcycle < Vehicle
  @wheels = 2
end

puts Vehicle.wheels # 4
puts Motorcycle.wheels # 2

推荐阅读