ruby - 子类实例变量在 Ruby 中更改父类(super class)实例变量

标签 ruby variables inheritance instance

<分区>

在这两篇文章中:

  1. Instance Variables Inheritance

  2. Can Ruby subclass instance variables _overwrite_ the superclass's (same name)?

人们在写关于在所有 OOP 语言中父类(super class)和派生类如何没有单独的对象,并且当您创建派生类的实例时,它也是父类(super class)的实例。有一个对象,它同时是两个类。

嗯,问题是我不明白?一个对象怎么能同时是两个类呢?如果实例变量当然使用相同的名称,它们怎么可能相同?

我的意思是我知道子类从父类(super class)获取方法,但我不明白它们如何共享实例变量?

我已经阅读了至少四本 Ruby 书籍,但我发现的全部内容是实例变量不通过继承链共享?

有人可以简要解释一下子类中的“实例变量”实际上是如何以及为什么存储在父类(super class)中的吗?

最佳答案

这里要理解的关键是:实例变量与当前对象(或实例)关联,而方法与类关联

这样做的原因是,如果创建的每个对象都与该类的所有其他对象具有相同的主体,那么您不希望为创建的每个对象都创建新方法。

另一方面,每个对象的实例变量必须是单独的,否则在改变值时你将得到一个完整的混搭。


考虑到这一点,让我们考虑以下示例:

class Foo
  def foo
    @var = :foo
  end
end

class Bar < Foo
  def bar
    @var = :bar
  end
end

让我们探索一下当我们创建一个新对象时会发生什么:

baz = Bar.new

目前,baz 没有任何实例变量。它只有一个指针,上面写着Bar is my class”

baz.class # => Bar

FooBaz 类没有任何诸如 @var 的关联。所以目前,没有人知道@var


当你在 baz 上调用一个方法时,方法定义在 Bar ancestors chain 中搜索:

baz.class.ancestors # => [Bar, Foo, Object, Kernel, BasicObject]

这里可以注意几点:首先,那里的东西是按继承顺序出现的。其次,Foo隐式继承自Object。第三,模块也可以是链的一部分(如 Kernel)。

baz.bar # => :bar

将找到链中第一个有方法 #bar 的东西并调用它。该值被分配给 @var 实例变量,它与对象 baz 关联,而不是类 FooBar.

baz.foo # => :foo

现在将使用 Foo 中的方法定义。但同样,@varbaz 中被更改。


一些供日后阅读的相关内容 (为简单起见,上面的一些内容并不完全准确):

  • 单例类
  • 类变量
  • 包括/前置模块
  • Class.superclass # => 模块
  • BasicObject#method_missing

关于ruby - 子类实例变量在 Ruby 中更改父类(super class)实例变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34636388/

相关文章:

ruby - 在模块上下文中向基类添加方法

ruby-on-rails - 机架测试需要机架应用程序,但没有给出

ruby-on-rails - 错误 Rails - libxml-Ruby

c++ - c++中变量的栈内存分配

php - 是否可以直接从 php 更改 php 源代码?

c++ - 从递归模板类继承

ruby-on-rails - 如果照片为 :title is included in form,CarrierWave 和嵌套表格保存空图像对象

performance - BASH:一次设置多个变量/性能

java - 将子类型集合分配给父类型

c++ - 为什么我需要在模板继承中使用范围解析?