Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby : how to prevent modification of an array instance variable through an attribute reader

sorry for this noob question... let's say we have :

class TestMe
 attr_reader :array

 def initialize
   @array = (1..10).to_a
 end

end

it is then possible to do :

>> a = TestMe.new
=> #<TestMe:0x00000005567228 @x=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]>
>> a.array.map! &:to_s
=> ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
>> a.array
=> ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
  • this clearly goes against encapsulation, doesn'it ?
  • is there any way to quickly protect the array variable from being changed ?
  • ... or do i need to implement a deep-copy reader every time my instance variable has "destructive" methods ?

EDIT i read somewhere it is "bad OO" to expose an array instance variable. If it's true, why ?

like image 769
m_x Avatar asked Feb 13 '12 10:02

m_x


1 Answers

You cannot do much with attr_reader, because attr_reader :array generates the following code:

def array; @array; end

If you don't want to expose array instance, you can return Enumerator of this array (external iterator). Enumerator is a good iterator abstraction and does not allow you to modify original array.

def array; @array.to_enum; end

What good for encapsulation and what not depends on the abstraction your class presents. Generally this is not good for encapsulation to expose internal state of an object, including internal array. You may want to expose some methods that operate on the @array instead of exposing @array (or even its iterator) itself. Sometimes this is fine to expose array - always look at the abstraction your class presents.

like image 112
Aliaksei Kliuchnikau Avatar answered Nov 15 '22 21:11

Aliaksei Kliuchnikau