Ruby 如何打印一个对象可以访问到的 instance_variables?

serveryang · 2023年12月12日 · 最后由 serveryang 回复于 2023年12月14日 · 501 次阅读

如何打印一个对象可以访问到的 instance_variables? 1、包含自己的实例变量。 2、包含继承来的实例变量。

目前找了一些资料没有找到怎么打印继承来的实例变量,这样导致无法观察整个对象的信息。

Object#instance_variables不够用?

haohaodehao 回复

不够用,这个只能看到问题中的第 1 点。 实际开发中,需要的第 2 点内容,就是继承链上的实例变量我也需要知道。

serveryang 回复

你想偏了,实例变量不会被继承,自然不存在“返回继承链上的实例变量”这样的方法

比如你的实例 叫 instance

instance.class.ancestors.each {|klass| puts klass.instance_variables}
Mark24 回复

那这打印的就是“类实例变量”了.... 不知道楼主真正的原始问题到底是什么

Ruby 和 Rails 貌似找不到直接的方法,不过可以尝试在底层的 class 里面定义一个方法,用当前 class 的所有实例变量减去 superclass 里面的所有实例变量,这样就获取到了 当前 class 里面定义的实例变量了。如果两个 class 之间有重合的实例变量就是继承过来的

Example

class Base
  def initialize
    @base = "base"
  end

  def current_class_instance_variables
    instance_variables - self.class.superclass.new.instance_variables
  end

  def current_class_inherited_instance_variables
    self.class.superclass.new.instance_variables & instance_variables
  end

end
class Application < Base
  def initialize()
    super
    @application = "application"
  end
end
class Post < Application
  def initialize()
    super
    @post = "post"
  end
end

class Article < Application
  def initialize()
    super
    @article = "article"
  end
end

Article.new.current_class_instance_variables
Post.new.current_class_instance_variables
Application.new.current_class_instance_variables
Base.new.current_class_instance_variables
Article.new.current_class_inherited_instance_variables
Post.new.current_class_inherited_instance_variables
Application.new.current_class_inherited_instance_variables
Base.new.current_class_inherited_instance_variables

输出结果如下

但是这样也有很多问题解决不了,比如在某个方法里面添加的实例变量,继承了一些抽象类之类或者实例变量被重写了的问题。

我和 3 楼理解的一样,实例变量不会被继承,只能通过这些奇技淫巧来处理

原始需求是这样的:实例对象访问一些 ancestors 不是属于自己类里定义的,实例类继承链上的类又动态 include 很多内容。最终使用实例的时候看到到处访问一些属性。debug 的时候就想 pp 完这个实例类继承链上的所有可以访问的实例属性。代码里有很多访问是父类的东西,如果不知道实例类可以访问所有的属性的话,看代码起来就比较奇怪,缺少对类的全局认识。 如果能 pp 完这个类的所有可以访问的属性,就对这个类有了全局认识。

最近在使用https://github.com/Arachni/arachni/这个框架,由于里面的动态定义太多了。调试的时候需要观察的东西比较多,如实例可以访问到的属性,实例方法。 同时又发现太多回调的使用,已经形成地狱回调了。一些奇怪的原始需求都是来自这个框架的使用。😀 😀 😀 😀

serveryang 回复

最终使用实例的时候看到到处访问一些属性

你看到的"属性"并不是实例变量,而是方法。

ruby 语言中并不太常用"属性"一词。代码中看到的形如 obj.size, obj.price 均为方法调用。而实例变量的访问,要么是在对象内部通过 @var_name 直接访问,要么是在外部通过 instance_variable_get, instance_exec 这样的代码探针来调用。

所以你需要的可能是 obj.methods 来返回所有的非私有方法

spike76 回复

😀 我后面试下 pp obj.methods 来观察下信息

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