0

我很难理解“动态方法”的概念。我发现这篇博文很有帮助,它声称

“动态方法”是具有在运行时计算然后定义的名称或主体的方法。

但是我怎么知道一个方法是动态定义的呢?

    class Foo
      def self.bar
        puts 'bar is statically defined'
      end

      define_method(:baz) do
        puts 'baz is dynamically defined'
      end
    end

    Foo.singleton_methods.include? :bar  #=> true
    Foo.instance_methods.include? :baz  #=> true 
    #??? shouldn't this be false according to the claim of 'dynamic methods'?
4

3 回答 3

4

“动态”和“静态”方法之间没有太大区别,但#source_location可能会给您一些提示。对于内置方法,#source_location返回 nil:

method( :puts ).source_location #=> nil

现在,为了演示“静态”和“动态”方法之间的区别,让我们安装pyper gem:。gem install pyperPyper gem 提供了 Lispy 思想car/cdr方法的扩展。(car表示“头”,即列表中的第一个元素。cdr表示“尾”,即除第一个元素之外的所有元素。)因为carcdr方法是由pyper “静态”定义的,所以它们#source_location是已知的:

require 'pyper'
x = ["See", "you", "later", "alligator"]

x.car
#=> "See"
x.cdr
#=> ["you", "later", "alligator"]
x.method( :car ).source_location
#=> ["/usr/local/lib/ruby/gems/2.0.0/gems/pyper-2.0.0/lib/pyper.rb", 12]
x.method( :cdr ).source_location
#=> ["/usr/local/lib/ruby/gems/2.0.0/gems/pyper-2.0.0/lib/pyper.rb", 13]

方法的返回值#source_location直接为您提供方法源来自的文件和行。但是,pyper也允许“动态”方法,这些方法尚未在静态源文件中定义:

x.τaτ # equivalent of #car
#=> "See"
x.τdeadτ # a custom method that sellects all letters except the 1st from the 4th word
#=> "lligator"
x.method( :τaτ ).source_location
#=> ["(eval)", 1]
x.method( :τdeadτ ).source_location
#=> ["(eval)", 1]

返回值["(eval)", 1]表明该方法是由eval语句定义的,如果您愿意,可以将其视为“动态”。

于 2013-09-09T03:02:04.720 回答
2
于 2013-09-09T06:56:14.220 回答
-1
  1. def bar只是一个语法糖define_method(:baz) do

  2. 实际上,“动态方法”和“普通方法”一旦定义就没有区别。

  3. define_method通常与 一起使用method_missing,下面的代码是“动态方法”的一个很好的例子

    class Foo
      def method_missing(meth, *args, &block)
        eigenclass = class << self; self; end
        eigenclass.class_eval do
          define_method(meth) do
            puts "method '#{meth}' is dynamically defined"
          end
        end
        send(meth, *args, &block)
      end
    end
    
    foo = Foo.new
    puts foo.methods.include? :bar  # => false
    foo.bar                         # => method 'bar' is dynamically defined
    puts foo.methods.include? :bar  # => true
    
于 2013-09-08T18:32:17.743 回答