3

Almost all decent resources about OOP in Ruby state the existence of access modifiers - keywords public, private and protected - and show how to properly use them. Fewer go to the extent of explaining that these modifiers are not keywords, but are actual methods and that calling them modifies visibility of all methods defined in the future in this particular class. However, I couldn't find any information about how they actually do that. Do they change a special internal variable, or do they alter properties of current scope/binding, or do they set some specific interpreter flag, or... or what?

I've done a little research on my own, but it left me even more confused than before. Consider the following code snippet:

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)

I always thought as def as a sort of optimized syntactic sugar for define_method with an additional quirk of creating new variable visibility scope, but, obviously, there seems to be more to it - methods created with def are affected by private/public modifiers, while those created with define_method are not. Furthermore, define_method doesn't have any arguments related to changing method's visibility, which led me to the conclusion that information about it must be stored in classes, not methods themselves - and so should be the flag set by access modifiers. But why then def so differs from define_method? What happens in the background? Does it check the flag set by access modifier methods and then adds itself into some special hidden register of class' private/protected methods?..

In short, I'm very confused and would be very glad if comeone could please clarify the issue. Thanks in advance!

DeFazer
  • 521
  • 3
  • 17

1 Answers1

1

Exactly?

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

With no arguments, sets the default visibility for subsequently defined methods to public. With arguments, sets the named methods to have public visibility.

Source:

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;
}

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

With no arguments, sets the default visibility for subsequently defined methods to private. With arguments, sets the named methods to have private visibility.

Source:

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;
}

protected http://apidock.com/ruby/Module/protected

With no arguments, sets the default visibility for subsequently defined methods to protected. With arguments, sets the named methods to have protected visibility.

source

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;
}

This doesn't really help with actual applications for this information, however. You may find more real-world applicable information on questions like What are the differences between "private", "public", and "protected methods"? and Why does Ruby have both private and protected methods?.

Community
  • 1
  • 1
Brad Werth
  • 17,411
  • 10
  • 63
  • 88
  • 1
    Thank you for the answer, but it's not exactly what I'm looking for. I already know how encapsulation in Ruby works and the results of calling these methods, I'm trying to understand what they do *under the hood*. Please, reread the question. I don't know about C++ much, so digging interpreter's source code by myself would only cause more confusion. Code snippets really help, yet could you please explain more about what `SCOPE_SET` and `set_method_visibility` do? Could the effects of `public` / `protected` / `private` be reproduced in pure Ruby, for instance, or are they hard-coded? Thanks! – DeFazer Mar 29 '17 at 02:17