views:

533

answers:

4

Is there any way to make instance variables "private"(C++ or Java definition) in ruby? In other words I want following code to result in an error.

class Base
  def initialize()
    @x = 10
  end
end

class Derived < Base
  def x
    @x = 20
  end
end

d = Derived.new
A: 

If you need an instance variable to be private, maybe this variable shouldn't be an instance variable in the first place.

marcgg
+5  A: 

Like most things in Ruby, instance variables aren’t truly “private” and can be accessed by anyone with d.instance_variable_get :@x.

Unlike in Java/C++, though, instance variables in Ruby are always private. They are never part of the public API like methods are, since they can only be accessed with that verbose getter. So if there's any sanity in your API, you don’t have to worry about someone abusing your instance variables, since they’ll be using the methods instead. (Of course, if someone wants to go wild and access private methods or instance variables, there isn’t a way to stop them.)

The only concern is if someone accidentally overwrites an instance variable when they extend your class. That can be avoided by using unlikely names, perhaps calling it @base_x in your example.

jleedev
isn't the issue here that in his code he can modify the `@x` variable from the derived class? That is contrary to what it is in C++ where a derived class _cannot_ access private data members. So, while it's true that 'instance variables in ruby are private' -- the important point is that it's a different kind of private to the meaning of private in C++
banister
+4  A: 

Unlike methods having different levels of visibility, Ruby instance variables are always private (from outside of objects). However, inside objects instance variables are always accessible, either from parent, child class, or included modules.

Since there probably is no way to alter how Ruby access @x, I don't think you could have any control over it. Writing @x would just directly pick that instance variable, and since Ruby doesn't provide visibility control over variables, live with it I guess.

As @marcgg says, if you don't want derived classes to touch your instance variables, don't use it at all or find a clever way to hide it from seeing by derived classes.

bryantsai
A: 

I think you shouldn't be trying to code C++ in Ruby. Since Ruby's a very dynamic & powerful language, there will always be a way to get to the private data.

Geo