“公共”,“私人”和“受保护”方法做了什么?

时间:2017-03-28 16:47:31

标签: ruby metaprogramming encapsulation

几乎所有关于Ruby中OOP的合适资源都说明存在访问修饰符 - 关键字publicprivateprotected - 并说明如何正确使用它们。更少解释这些修饰符是不是关键字,但是实际方法并且调用它们会修改此特定类中将来定义的所有方法的可见性。但是,我找不到关于他们实际上是如何的任何信息。他们是否更改了一个特殊的内部变量,或者他们是否更改了当前范围/绑定的属性,还是设置了一些特定的解释器标志,或者......或者是什么?

我自己做了一些研究,但它让我比以前更加困惑。请考虑以下代码段:

class Test
    public
    define_method :public_define_method do 
        puts 'Public define_method'
    end

    private
    define_method :private_define_method do 
        puts 'Private define_method'
    end

    public
    def public_def
        puts 'Public def'
    end

    private
    def private_def
        puts 'Private def'
    end
end

t = Test.new

t.public_define_method
t.private_define_method
t.public_def
t.private_def

#Output:
#> Public define_method
#> Private define_method
#> Public def
#> sandbox.rb:29:in `<main>': private method `private_def' called for #<Test:0x00000001cdfd38> (NoMethodError)

我一直认为defdefine_method的一种优化语法糖,另外还有一个创建新的变量可见范围的怪癖,但显然,它似乎还有更多 - 创建的方法def / private修饰符会影响public,而使用define_method创建的修饰符则不会。此外,define_method doesn't have任何与更改方法可见性相关的参数,这使我得出结论,关于它的信息必须存储在类中,而不是方法本身 - 因此应该是访问修饰符设置的标志。但是为什么defdefine_method有所不同?在后台会发生什么?它是否检查由访问修饰符方法设置的标志,然后将其自身添加到类'private / protected方法的某个特殊隐藏寄存器中?..

简而言之,我很困惑,如果有人能够澄清问题,我会很高兴。提前谢谢!

1 个答案:

答案 0 :(得分:1)

完全?

公开 http://apidock.com/ruby/Module/public

  

如果没有参数,则将后续定义的方法的默认可见性设置为public。使用参数,将命名方法设置为具有公共可见性。

来源:

static VALUE
rb_mod_public(int argc, VALUE *argv, VALUE module)
{
    secure_visibility(module);
    if (argc == 0) {
        SCOPE_SET(NOEX_PUBLIC);
    }
    else {
        set_method_visibility(module, argc, argv, NOEX_PUBLIC);
    }
    return module;
}

私人 http://apidock.com/ruby/Module/private

  

如果没有参数,则设置后续的默认可见性   私有的定义方法。使用参数,将命名方法设置为   有私人知名度。

来源:

static VALUE
rb_mod_private(int argc, VALUE *argv, VALUE module)
{
    secure_visibility(module);
    if (argc == 0) {
        SCOPE_SET(NOEX_PRIVATE);
    }
    else {
        set_method_visibility(module, argc, argv, NOEX_PRIVATE);
    }
    return module;
}

受保护 http://apidock.com/ruby/Module/protected

  

如果没有参数,则设置后续的默认可见性   定义的受保护方法。使用参数,设置命名方法   保护知名度。

static VALUE
rb_mod_protected(int argc, VALUE *argv, VALUE module)
{
    secure_visibility(module);
    if (argc == 0) {
        SCOPE_SET(NOEX_PROTECTED);
    }
    else {
        set_method_visibility(module, argc, argv, NOEX_PROTECTED);
    }
    return module;
}

但是,这对于此信息的实际应用程序并没有实际帮助。您可以在What are the differences between "private", "public", and "protected methods"?Why does Ruby have both private and protected methods?等问题上找到更多真实的适用信息 enter image description here