Ruby 在类继承时关于类实例保存 class 的问题

xiaojin2630 · 2021年05月12日 · 最后由 xiaojin2630 回复于 2021年05月14日 · 242 次阅读

使用类变量保存 subclass 是没问题的:

class Base
    @@a = []

    def self.inherited(subclass)
        puts "subclass = #{subclass}"
        @@a << subclass
    end 

    def self.out
        p @@a
    end 

end 

class C1 < Base
end

class D < C1
end

Base.out

Base.out 输出为: subclass = C1 subclass = D [C1, D]

但我改成类实例变量,就会报错:

class Base
    @list = []

    def self.inherited(subclass)
        puts "subclass = #{subclass}"
        @list << subclass
    end 

    def self.out
        p @list
    end 

end 

class C1 < Base
end

class D < C1
end

Base.out

subclass = C1 subclass = D 1.rb:7:in inherited': undefined method<<' for nil:NilClass (NoMethodError) from 1.rb:19:in `'

但若是将 class D < Base 时,再执行 Base.out 就不报错,输出正确了。 为什么 class D < C1 时,会报错呢?

类变量@@list 从父类到子类是共享的,实例变量@list是每个对象独有的,类也是对象。所以 C1 不会继承@list = [],也就是 nil,因此报错

类实例属于类对象本身,不能够被子类继承,类实例变量不要求访问前必须赋值,不赋值它的值就是 nil,实例变量:作用于对象的区域,会在这个对象的作用域内寻找。类变量:作用于类,类中都能找到,子类继承,相当于作用域子类,子类中也都能找到。

@radiocontroller @stargwq 感谢两位的解答,我明白了。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号