How to create a private class method?

后端 未结 8 1317
北荒
北荒 2020-12-02 04:43

How come this approach of creating a private class method works:

class Person

  def self.get_name
    persons_name
  end

  class << self

    private         


        
8条回答
  •  一生所求
    2020-12-02 04:55

    Ruby seems to provide a poor solution. To explain, start with a simple C++ example that shows access to private class methods:

    #include 
    
    class C
    {
        public:
            void instance_method(void)
            {
                std::cout << "instance method\n";
                class_method();  // !!! LOOK !!! no 'send' required. We can access it
                                 // because 'private' allows access within the class
            }
        private:
            void static class_method(void) { std::cout << "class method\n"; }
    };
    
    int main()
    {
        C c;
    
        c.instance_method(); // works
        // C::class_method() does not compile - it's properly private
        return 0;
    }
    

    Running the above

       % ./a.out
       instance method
       class method
    

    Now Ruby does not seem to provide the equivalent. Ruby's rules, I think, are that private methods must not be accessed with a receiver. That is,

    inst.pvt_method  # FAILS
    pvt_method # WORKS only within the class (good)
    

    That's OK for private instance methods, but causes problems with private class methods.

    I would like Ruby to function this way:

    class C
        def instance_method
            STDOUT << "instance method\n"
    
            # Simple access to the private class method would be nice:
            class_method   # DOES NOT WORK. RUBY WON'T FIND THE METHOD
            C.class_method # DOES NOT WORK. RUBY WON'T ALLOW IT
    
            # ONLY THIS WORKS. While I am happy such capability exists I think
            # the way 'send' should be used is when the coder knows he/she is
            # doing a no-no.  The semantic load on the coder for this is also
            # remarkably clumsy for an elegant language like ruby.
            self.class.send(:class_method)
        end
    
        private_class_method def self.class_method() STDOUT << "class method\n"; end
    end
    

    But, alas, the above does not work. Does someone know a better way?

    When I see 'send' prior to a method, it's a clear sign the code is violating the intent of the API's designer, but in this case the design is specifically to have an instance method of the class call the private class method.

提交回复
热议问题