代码之家  ›  专栏  ›  技术社区  ›  Lusheez

获取类的attr\u reader、writer或accessor oustide

  •  1
  • Lusheez  · 技术社区  · 8 年前

    我目前正在用ruby进行一些元编程,并试图隔离类的方法(该类位于另一个文件中,我需要它)。多亏了克拉斯,我能掌握所有的方法。public\u instance\u方法(false),但在sametime中,给定的数组也具有类的所有属性。我怎样才能隔离他们?在其他与此相关的问题中,他们建议使用klass。instance\u变量,但当我这样做时,它只返回一个空数组。

    我似乎无法理解这一点。我不明白为什么现在还没有一个专门的方法。。。

    例如:

    我在此类文件中有:

    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 回复  |  直到 8 年前
        1
  •  1
  •   Maciej Nędza    8 年前

    对于定义如下的类:

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

    可以使用查找公共非attr实例方法 public_instance_methods instance_variables 方法。

    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]
    
        2
  •  1
  •   Max    8 年前

    这是不可能的。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
    
    推荐文章