8

以示例类为例:

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

当我以详细模式运行它时,Ruby 会向我抛出警告:

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

为什么不建议这样做?

4

2 回答 2

2

因为在大多数情况下,定义从外部看不到的 getter/setter 没有多大意义。我们通常attr_accessor仅用于在类之外公开实例变量。但是,private关键字通过使生成的 getter/setter 方法对外界不可见而破坏了这个目的。

您想要使用私有 setter/getter 的唯一原因是当涉及一些额外的逻辑时。但是,在这种情况下,无论如何,您都必须使用 手动定义这些方法def

于 2013-08-19T07:55:27.547 回答
1

虽然我接受了@padde的回答,但我想分享一些代码以供将来参考。

我想检查@Babai关于属性方法的默认访问级别的答案。

这就是它的工作原理。我将在源代码上进行演示2.0.0-p247

这是的来源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;
}

如您所见,它rb_attr为每个参数调用该函数。(我猜argcargument counter.)所以我们必须查看rb_attr源代码以了解这一切是如何工作的:

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 */
}

如您所见,解释器检查访问级别是否为NOEX_PRIVATE,如果是则引发错误。

于 2013-08-19T09:10:43.687 回答