> -----Original Message-----
> From: Josh Cheek [mailto:josh.cheek / gmail.com]
> Sent: 07 November 2009 02:43
> To: ruby-talk ML
> Subject: Re: encapsulation issue
> 
> On Fri, Nov 6, 2009 at 7:50 AM, James French
> <James.French / naturalmotion.com
> > wrote:
> 
> > Hi,
> >
> > Is there any way of providing read only access to an array? (problem
> shown
> > by code below).
> >
> > class A
> >
> >  def initialize
> >    @dependencies = []
> >  end
> >
> >  # intended to be read only access
> >  def dependencies
> >    @dependencies
> >  end
> >
> >  def addDependency(d)
> >    @dependencies << d
> >    puts "adding #{d}"
> >  end
> > end
> >
> >
> > a = A.new
> > a.addDependency("foo")
> > a.dependencies << "bar" # encapsulation subverted
> >
> > puts a.dependencies   # foo and bar both in array
> >
> >
> > Any suggestions appreciated,
> > James
> >
> >
> Ruby is a dynamic language, as David pointed out, you can always get
> around
> whatever someone does. I think the point isn't so much to make it
> impossible
> for them to do something, but rather to make it clear how it was
> anticipated
> that it would be used. If they want to go so far as to override the
> methods,
> or perform instance_eval to get at the variable, then I'd take that as
> a
> very deliberate effort, so due to their determination to get around
> your
> design, I would just assume that they had a legitimate reason to do so,
> or
> at least if it blows up, they'll have no cause to be upset with you for
> it.
> 
> I don't know how you are trying to use the class, that you feel the
> need to
> return an array that cannot be altered, but you could define methods
> which
> give this functionality without ever exposing the array itself,
> something
> like this:
> 
> 
> # consider defining methods to give the functionality you might want
> # without exposing the guts of your class to the world
> class Configuration
>   def initialize()       @dependencies = []  end
>   def add_dependency(d)  @dependencies << d  end
> 
>   def each_dependency
>     @dependencies.each { |dep| yield dep }
>   end
> end
> 
> config = Configuration.new
> config.add_dependency :dependency1
> config.add_dependency :dependency2
> config.add_dependency :dependency3
> 
> config.each_dependency do |dependency|
>   puts "I am accessing #{dependency}, " \
>        "without ever seeing the array."
> end
> 
> 
> 
> # Of course, they can always get around whatever you have done,
> # in the above, there is no way to get at @dependencies from the
> # outside world, but in their code they could just add the code below
> class Configuration
>   attr_accessor :dependencies
> end
> 
> p config.dependencies
> 
> __END__
> Ruby is not about strict rigid code, or forcing people to use it
> a certain way, it is dynamic. You have made your intentions clear,
> at this point, if the user is not satisfied with your intentions,
> then you must trust them to know what is best for their needs.
> Something like this will not occur by accident, they have quite
> deliberately decided that they need to break the encapsulation.

Thanks for the answer - appreciate it, and have taken it on board.