【问题标题】:Meaning of Syntax for Ruby ModuleRuby 模块语法的含义
【发布时间】:2018-02-02 21:12:08
【问题描述】:

我一直在阅读一些教程来查找此信息,但没有看到任何直接解决此问题的内容。

我已经多次在模块上看到以下语法:

module MyModule

   def run()
      puts "running"
   end
end

我也见过类似这样的语法:

module MyModule

   def MyModule.run()
      puts "running"
   end
end

在方法之前包含模块名称有什么好处?反之亦然?

【问题讨论】:

  • 你试过调用上面的代码吗?如果有的话应该很明显。
  • @engineersmnky 我有,但除了创建一个命名空间以使函数不会相互影响之外,我没有看到其他意义。
  • 在第二个例子中你可以调用MyModule.run。你能在第一个例子中做同样的事情吗?
  • 拳头将允许您将此方法混合到其他类中,例如class A; include MyModule; end; 将允许您致电 A.new.runclass A; extend MyModule; end; 将允许您致电 A.run。在第二个示例中,run 方法绑定到作为接收者的MyModule,并且必须调用为MyModule.run

标签: ruby


【解决方案1】:
module MyModule
   def MyModule.run()
      puts "running"
   end
end

完全一样:

module MyModule
   def self.run()
      puts "running"
   end
end

通常使用def self.run,因为当您必须更改模块名称时它会更好,并且更符合习惯。我看不出写def MyModule.run有什么好处。

【讨论】:

  • "self" 指的是一个将该模块用作混合的类,对吧?
  • self 在实例方法定义之外是指self 内的模块。
  • @CannonMoyer 在模块主体中,selfMyModule 是相同的。
  • “它是”?哪一个”?他们正在展示两个版本。
【解决方案2】:

这与模块无关。这只是普通的方法定义语法。

Ruby 中方法定义的语法是

def <target>.<selector>(<parameters>)
  # …
end

例如:

def foo.bar(baz)
end

这将在foo 引用的对象上定义一个名为bar 的方法(更准确地说,在foo 引用的对象的单例类中),具有一个强制位置参数,其绑定名为@987654326 @。

与消息发送一样,您可以省略目标,Ruby 将使用隐式默认值。在消息发送中,隐式默认为self,带有方法定义,默认为所谓的default definee,它通常是最近的词法封闭模块定义体。

所以,

def MyModule.run

表示“在对象MyModule(或更准确地说是在对象MyModule的单例类中)定义一个名为run的方法”,而

def run

表示“在默认的definee中定义一个名为run的方法”,即最近的词法封闭模块定义体,在本例中为MyModule

第二版将run定义为MyModule实例方法,第一版将run定义为@的单例类的实例方法987654338@,我们有时称之为“模块方法”或“模块函数”。

请注意,第一个版本通常更习惯地写为

def self.run

【讨论】:

    【解决方案3】:

    这是关于使用模块作为静态命名空间与使用模块作为混合。看看下面的代码(在 cmets 中输出):

    module MyModule
    
       def MyModule.run()
          puts "#{self}: running"
       end
    
       def run()
          puts "#{self}: running"
       end
    
    
    end
    
    class Foo
      include MyModule
    end
    
    MyModule.run #MyModule: running
    foo = Foo.new
    foo.run #<Foo:0x007f9b269bf028>: running
    

    在第一种用法中,模块基本上只是充当命名空间,您可以将方法附加到该命名空间。 第二,模块混入到类Foo中。这意味着它的行为就好像 run 方法首先在 foo 类中定义;如果您愿意,您可以引用未在模块中定义的实例变量 @bar,而仅在 Foo 类中定义。

    【讨论】:

    • “如果你愿意,你可以引用在模块中没有定义的实例变量@bar,但只能在 Foo 类中” 我不推荐这个部分因为这推断Module 应该比Class 包含更深入的知识,反之亦然。如果您必须以这种方式使用变量,则应将它们依赖注入到模块中定义的方法中,例如def run(arg=self); "#{arg}: running"; end 然后Foo 可以调用run(@bar)
    • 也许是这样 - OP 似乎从根本上对 mixin 的概念感到困惑,我认为这种观察可能会有所帮助。
    【解决方案4】:

    我猜两者都是一样的,但是如果我们在类中调用模块方法,那么我们必须给出

    ModuleName.method_name()
    

    以便它可以理解包含或特定模块需要此方法

    【讨论】:

    • 它们根本不一样(除了这个简单的例子都包含相同的方法体)
    猜你喜欢
    • 1970-01-01
    • 2016-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-19
    • 2011-09-24
    • 1970-01-01
    相关资源
    最近更新 更多