> -----Original Message----- > From: Josh Cheek [mailto:josh.cheek / gmail.com] > Sent: 07 November 2009 02:43 > To: ruby-talk ML > Subject: Re: encapsulation issue >=20 > On Fri, Nov 6, 2009 at 7:50 AM, James French > <James.French / naturalmotion.com > > wrote: >=20 > > Hi, > > > > Is there any way of providing read only access to an array? (problem > shown > > by code below). > > > > class A > > > > def initialize > > @dependencies =3D [] > > end > > > > # intended to be read only access > > def dependencies > > @dependencies > > end > > > > def addDependency(d) > > @dependencies << d > > puts "adding #{d}" > > end > > end > > > > > > a =3D 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. >=20 > 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: >=20 >=20 > # 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 =3D [] end > def add_dependency(d) @dependencies << d end >=20 > def each_dependency > @dependencies.each { |dep| yield dep } > end > end >=20 > config =3D Configuration.new > config.add_dependency :dependency1 > config.add_dependency :dependency2 > config.add_dependency :dependency3 >=20 > config.each_dependency do |dependency| > puts "I am accessing #{dependency}, " \ > "without ever seeing the array." > end >=20 >=20 >=20 > # 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 >=20 > p config.dependencies >=20 > __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.