Why won't Ruby allow me to specify self as a receiver inside a private method?

后端 未结 4 1537
南旧
南旧 2021-01-13 15:40

Ruby as an Object Oriented Language. What that means is whatever message I send, I strictly send it on some object/instance of class.

Example:

 class         


        
相关标签:
4条回答
  • 2021-01-13 16:08

    self means the current instance of the object you are in.

    class Test
      def test1
        self
      end
    end
    

    Calling Test.new.test1 will return something like #<Test:0x007fca9a8d7928>.
    This is the instance of the Test object you are currently using.

    Defining a method as private means it can only be used inside the current object.
    When using self.test2, you are going outside of the current object (you get the instance) and you call the method.
    So you are calling a private methods as if you were not in the object, which is why you can't.

    When you don't specify self, you remain inside the current object.
    So you can just call the method. Ruby is smart enough to know that test2 is a method and not a variable and to call it.

    0 讨论(0)
  • 2021-01-13 16:08

    This has been changed in Ruby 2.7 (December 2019): self.foo() is now also valid for a private method foo.

    References:

    • https://rubyreferences.github.io/rubychanges/2.7.html#selfprivate_method
    • https://bugs.ruby-lang.org/issues/11297
    • https://bugs.ruby-lang.org/issues/16123
    0 讨论(0)
  • 2021-01-13 16:11

    where is the object that I am sending method on

    It's self. Whenenver you don't specify a receiver, the receiver is self.

    The definition of private in Ruby is that private methods can only be called without a receiver, i.e. with an implicit receiver of self. Interestingly, it didn't bother you at all with the puts method which is also a private instance method ;-)

    Note: there's an exception to this rule. Private setters can be called with an explicit receiver, as long as the receiver is self. In fact, they must be called with an explicit receiver, because otherwise there would be an ambiguity with local variable assignments:

    foo = :fortytwo      # local variable
    self.foo = :fortytwo # setter
    
    0 讨论(0)
  • 2021-01-13 16:25

    The Problem

    In Ruby, private methods can't be called directly with an explicit receiver; self doesn't get any special treatment here. By definition, when you call self.some_method you are specifying self as the explicit receiver, so Ruby says "No!"

    The Solution

    Ruby has rules for its method lookups. There may be a more canonical source for the rules (other than going to the Ruby source), but this blog post lays out the rules right at the top:

    1) Methods defined in the object’s singleton class (i.e. the object itself)
    2) Modules mixed into the singleton class in reverse order of inclusion
    3) Methods defined by the object’s class
    4) Modules included into the object’s class in reverse order of inclusion
    5) Methods defined by the object’s superclass, i.e. inherited methods
    

    In other words, private methods are first looked up in self without requiring (or allowing) an explicit receiver.

    0 讨论(0)
提交回复
热议问题