ways to define a global method in ruby

前端 未结 2 1926
甜味超标
甜味超标 2021-02-09 08:15

I\'m writing a small gem, and I want to define a DSL-like method, pretty much the same as the desc and task methods in Rake.

R

2条回答
  •  滥情空心
    2021-02-09 08:58

    Just to extend the answer given by bor1s, about the private methods:

    In ruby you have "private" and "protected" methods. What bor1s says, is correct when talking about "protected" methods. Declaring a method "private" additionally prevents other instances of the same class from using the method.

    When you call a "private" method, you cannot use a dot in front of it - you cannot even use self., even though using or omitting self has usually the same effect.

    class Xyzzy
      private
      def foo
        puts "Foo called"
      end
    
      public
      def do_it
        foo       # <= Is OK
        self.foo  # <= raises NoMethodError
      end
    end
    
    Xyzzy.new.do_it
    

    If you change 'private' to 'protected' in the code above, no error will be raised.

    And about modules:

    The final result of defining a method in Kernel and extending Kernel with the method defined in some module is the same: in both cases the method is global.

    Using a module is just a little more elegant, as it groups your changes in one place, but I would say it's a matter of personal taste.

    Usually you do not include methods in Kernel or Object (as it may be a little dangerous), but you include (or extend) a specific class or object which needs these methods, and in this case you need your methods grouped in a module.

    Even Rake in version 0.9.0 stopped including the DSL commands in Object:

    == Version 0.9.0

    • Incompatible *change*: Rake DSL commands ('task', 'file', etc.) are no longer private methods in Object. If you need to call 'task :xzy' inside your class, include Rake::DSL into the class. The DSL is still available at the top level scope (via the top level object which extends Rake::DSL).

提交回复
热议问题