Question

Take the example class:

# in ./example.rb
class Example
  private
    attr_accessor :name
end

When I run it in verbose mode, Ruby throws warnings at me:

$ ruby -W2 ./example.rb
example.rb:3: warning: private attribute?

Why is this not recommended?

Was it helpful?

Solution

Because it doesn't make much sense to define a getter/setter that is not visible from the outside in most cases. We generally use attr_accessor only to expose an instance variable outside of the class. However, the private keyword defeats this purpose by making the generated getter/setter methods invisible to the outside world.

The only reason you would want to use a private setter/getter is when there is some additional logic involved. In this case, however, you would have to define those methods manually with def, anyway.

OTHER TIPS

Although I've accepted @padde's answer, I would like to share some code for future reference.

I wanted to check @Babai's answer about the default access levels of the attribute methods.

So here's how it works. I'll demonstrate on the source from 2.0.0-p247.

This is the source of attr_accessor:

static VALUE
rb_mod_attr_accessor(int argc, VALUE *argv, VALUE klass)
{
    int i;

    for (i=0; i<argc; i++) {
rb_attr(klass, rb_to_id(argv[i]), TRUE, TRUE, TRUE);
    }
    return Qnil;
}

As you can see, it's calling the rb_attr function for each argument. (I'm guessing argc stands for argument counter.) So we have to look at the rb_attr source to understand how this all works:

void
rb_attr(VALUE klass, ID id, int read, int write, int ex)
{
    const char *name;
    ID attriv;
    VALUE aname;
    rb_method_flag_t noex;

    if (!ex) {
      noex = NOEX_PUBLIC;
    }
    else {


      if (SCOPE_TEST(NOEX_PRIVATE)) {
        noex = NOEX_PRIVATE;
        rb_warning((SCOPE_CHECK(NOEX_MODFUNC)) ?
          "attribute accessor as module_function" :
          "private attribute?");
      }
      else if (SCOPE_TEST(NOEX_PROTECTED)) {
        noex = NOEX_PROTECTED;
      }
      else {
        noex = NOEX_PUBLIC;
      }
    }

    /* more logic that's not relevant for this explanation */
}

As you can see, the interpreter checks if the access level is NOEX_PRIVATE and raises errors if it is.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top