From: Gavin Kistner Date: 2005-06-02T11:11:24+09:00 Subject: Re: Implementing a Read-Only array On Jun 1, 2005, at 4:11 PM, Brian Schr�der wrote: >> Gavin Kistner wrote: >>>>> affectors = %w| << []= clear concat delete delete_at delete_if >>>>> fill flatten! insert map! pack pop push reject! replace reverse! >>>>> shift slice! sort! uniq! unshift | > > Though this means that you have to override all methods that can > change the array. I'd shurely forget something in this case. You > forgot e.g. #clear. Therefore I'd propose to explicitly delegate the > needed methods for the application because this is easier to control. But again, that way prevents users' convenience methods for Arrays/ Enumerables from being available. The 'affectors' list above is (I believe) precisely the list of methods that can change the array. (Except I accidentally included pack, which is non-mutating.) The final solution that I'm currently using is: require 'delegate' class ReadOnlyArray < DelegateClass(Array) mutators = %w| << []= clear concat delete delete_at delete_if fill | mutators.concat %w| flatten! insert map! pop push reject! replace | mutators.concat %w| reverse! shift slice! sort! uniq! unshift | mutators.each do |name| define_method( name ){ raise "#{self} is read-only!" } end end a = [1,2,3] ro = ReadOnlyArray.new( a ) a << 4 p ro #=> [1, 2, 3, 4] p ro.reverse #=> [4, 3, 2, 1] p ro.reverse! /Users/gkistner/Desktop/tmp.rb:8:in `reverse!': 1234 is read-only! (RuntimeError) from /Users/gkistner/Desktop/tmp.rb:8:in `reverse!' from /Users/gkistner/Desktop/tmp.rb:18