获取该类的attr_reader,writer或accessor oustide

时间:2018-03-23 12:35:44

标签: ruby methods metaprogramming

我目前正在使用ruby进行一些元编程,而我正在尝试隔离类的方法(该类在另一个文件中,我通过require得到)。由于klass.public_instance_methods(false),我可以获得所有方法,但同时我给出的数组也具有该类的所有属性。我怎么能把它们隔离开来?在关于SO的其他相关问题中,他们建议使用klass.instance_variables,但是当我这样做时,它只返回一个空数组。

我似乎无法绕过那个人。我不明白为什么还没有专门用于此的方法......

例如:

我在这个课程中有一个文件:

class T
    attr_reader:a
    def initialize(a)
        @a = a
    end
    def meth
        #code here
    end
end

而且,在另一个文件中,我有

require_relative 'T.rb'
class meta
   def initialize
       methods = T.public_instance_methods(false) #=> here methods = [:a,:meth] but I would want only to have [:meth]
       #rest of code
   end
end

2 个答案:

答案 0 :(得分:1)

对于这样定义的类:

class Klass
    attr_accessor :variable
    def initialize(variable)
        @variable = variable
    end

    def method
    end
end

您可以使用public_instance_methodsinstance_variables方法找到公共非attr实例方法。

public_instance_methods  = Klass.public_instance_methods(false)
#  [:method, :variable, :variable=]

instance_variables = Klass.new(nil).instance_variables
# [:@variable]

getters_and_setters = instance_variables
                        .map(&:to_s)
                        .map{|v| v[1..-1] }
                        .flat_map {|v| [v, v + '=']}
                        .map(&:to_sym)
# [:variable, :variable=]

without_attr = public_instance_methods - getters_and_setters
# [:method]

答案 1 :(得分:1)

这是不可能的。 Ruby的“属性”是完全正常的方法。没有办法将它们与其他方法区分开来。例如,这两个类完全无法区分:

class Foo
   attr_reader :bar
end

class Foo
   def bar
     @bar
   end
end

您可以尝试聪明并根据实例变量过滤掉它们,但这很危险:

class Foo
  # can filter this out using @bar
  attr_writer :bar
  def initialize
    @bar = []
  end
end

class Foo
  def initialize
    @bar = []
  end

  # this looks the same as above, but isn't a normal attribute!
  def bar= x
    @bar = x.to_a
  end
end