是否可以在方法内部使用方法?

Tri*_*rip 84 ruby methods

我在方法中有一个方法.内部方法依赖于正在运行的变量循环.这是个坏主意吗?

Jör*_*tag 161

更新:由于这个答案最近似乎引起了一些兴趣,我想指出有关Ruby问题跟踪器的讨论要删除这里讨论的功能,即禁止在方法体内部进行方法定义.


不,Ruby没有嵌套方法.

你可以这样做:

class Test1
  def meth1
    def meth2
      puts "Yay"
    end
    meth2
  end
end

Test1.new.meth1
Run Code Online (Sandbox Code Playgroud)

但这不是嵌套方法.我再说一遍:Ruby 没有嵌套方法.

这是一个动态方法定义.当你跑步时meth1,meth1将会执行尸体.正好恰好定义了一个名为的方法meth2,这就是为什么在运行meth1一次之后,你可以调用meth2.

但在哪里meth2定义?好吧,它显然没有被定义为嵌套方法,因为Ruby 中没有嵌套方法.它被定义为以下的实例方法Test1:

Test1.new.meth2
# Yay
Run Code Online (Sandbox Code Playgroud)

此外,每次运行时显然都会重新定义meth1:

Test1.new.meth1
# Yay

Test1.new.meth1
# test1.rb:3: warning: method redefined; discarding old meth2
# test1.rb:3: warning: previous definition of meth2 was here
# Yay
Run Code Online (Sandbox Code Playgroud)

简而言之:不,Ruby 支持嵌套方法.

另请注意,在Ruby中,方法体不能是闭包,只能是块体.这几乎消除了嵌套方法的主要用途的情况下,因为即使 Ruby的支持嵌套的方法,你不能在嵌套方法使用外部方法的变量.


更新继续:在稍后阶段,这个语法可能会被重新用于向Ruby添加嵌套方法,这将按照我描述的方式运行:它们将作用于其包含方法,即在其包含方法之外不可见和不可访问身体.并且可能,他们可以访问其包含方法的词法范围.但是,如果您阅读我上面链接的讨论,您可以观察到matz严重违反嵌套方法(但仍然用于删除嵌套方法定义).

  • 我感觉Ruby可能没有嵌套方法. (114认同)
  • @Mark Thomas:我忘了提到Ruby没有嵌套方法吗?:-)说真的:在我写这个答案的时候,已经有三个答案,每个答案都声称Ruby*有*嵌套方法.尽管公然出现了错误,但其中一些答案甚至还得到了赞成.尽管错误,OP仍然接受了一个人.回答用来证明Ruby支持嵌套方法的代码片段,实际上证明了相反的情况,但显然,upvoters和OP实际上都没有打算检查.所以,我为每一个错误的答案给出了一个正确答案.:-) (15认同)
  • 当你意识到这些只是修改表的内核的指令,并且方法,类和模块都只是表中的条目而不是真正的实际,当你看到Matrix的样子时,你变得像Neo.那么你真的可以成为哲学并说除了嵌套方法之外,甚至没有方法.甚至没有特工.它们是矩阵中的程序.即使你吃的多汁牛排也只是一张桌子上的入口. (9认同)
  • 但是,您可能还会显示如何在DRYness方法中创建闭包lambda,或者运行递归. (6认同)
  • 没有方法,您的代码只是The Matrix中的模拟 (3认同)
  • 注意:如果在调用解释器时通过`-w`启用ruby警告,或者在代码中使用`$ -w = true`,则只会看到"方法重新定义"警告. (2认同)

Sup*_*ver 12

实际上这是可能的.你可以使用procs/lambda.

def test(value)
  inner = ->() {
    value * value
  }
  inner.call()
end
Run Code Online (Sandbox Code Playgroud)

  • 你没错,但你的答案措辞是实现嵌套方法的解决方案.实际上,你只是使用不是方法的过程.除了声称要解决"嵌套方法"之外,这是一个很好的答案 (2认同)
  • 实际的嵌套方法能够做什么,而这个过程却不能,或者会做得很差? (2认同)

iir*_*ekm 5

不,不,Ruby确实具有嵌套方法。检查一下:

def outer_method(arg)
    outer_variable = "y"
    inner_method = lambda {
      puts arg
      puts outer_variable
    }
    inner_method[]
end

outer_method "x" # prints "x", "y"
Run Code Online (Sandbox Code Playgroud)

  • inner_method不是方法,它是一个函数/ lambda / proc。没有任何类的关联实例,因此它不是方法。 (9认同)