How do I add 'each' method to Ruby object (or should I extend Array)?

前端 未结 7 1480
抹茶落季
抹茶落季 2021-01-30 04:00

I have an object Results that contains an array of result objects along with some cached statistics about the objects in the array. I\'d like the Results object to

7条回答
  •  一向
    一向 (楼主)
    2021-01-30 04:56

    If you create a class Results that inherit from Array, you will inherit all the functionality.

    You can then supplement the methods that need change by redefining them, and you can call super for the old functionality.

    For example:

    class Results < Array
      # Additional functionality
      def best
        find {|result| result.is_really_good? }
      end
    
      # Array functionality that needs change
      def compact
        delete(ininteresting_result)
        super
      end
    end
    

    Alternatively, you can use the builtin library forwardable. This is particularly useful if you can't inherit from Array because you need to inherit from another class:

    require 'forwardable'
    class Results
      extend Forwardable
      def_delegator :@result_array, :<<, :each, :concat # etc...
    
      def best
        @result_array.find {|result| result.is_really_good? }
      end
    
      # Array functionality that needs change
      def compact
        @result_array.delete(ininteresting_result)
        @result_array.compact
        self
      end
    end
    

    In both of these forms, you can use it as you want:

    r = Results.new
    r << some_result
    r.each do |result|
      # ...
    end
    r.compact
    puts "Best result: #{r.best}"
    

提交回复
热议问题