以示例类为例:
# in ./example.rb
class Example
private
attr_accessor :name
end
当我以详细模式运行它时,Ruby 会向我抛出警告:
$ ruby -W2 ./example.rb
example.rb:3: warning: private attribute?
为什么不建议这样做?
以示例类为例:
# in ./example.rb
class Example
private
attr_accessor :name
end
当我以详细模式运行它时,Ruby 会向我抛出警告:
$ ruby -W2 ./example.rb
example.rb:3: warning: private attribute?
为什么不建议这样做?
因为在大多数情况下,定义从外部看不到的 getter/setter 没有多大意义。我们通常attr_accessor
仅用于在类之外公开实例变量。但是,private
关键字通过使生成的 getter/setter 方法对外界不可见而破坏了这个目的。
您想要使用私有 setter/getter 的唯一原因是当涉及一些额外的逻辑时。但是,在这种情况下,无论如何,您都必须使用 手动定义这些方法def
。
虽然我接受了@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
为每个参数调用该函数。(我猜argc
是argument 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
,如果是则引发错误。