ruby.扩展所需的帮助

jde*_*dee 2 ruby

特定

module Foo
  def bar
    puts "foobar"
  end
end
Run Code Online (Sandbox Code Playgroud)

我可以

String.extend(Foo)
Run Code Online (Sandbox Code Playgroud)

结果呢

String.bar # => "foobar"
Run Code Online (Sandbox Code Playgroud)

为什么这不起作用?:

a = String.new
a.bar # => NoMethodError: undefined method `bar' for "":String
Run Code Online (Sandbox Code Playgroud)

是因为'a'现在和实例和.extend只对类方法有效吗?为什么它会失去我通过.extend给String的"新"功能?

rrj*_*mie 6

Ruby允许您以两种方式将模块中的方法添加到类中:extendinclude.

使用您提供的模块:

module Foo
  def bar
    puts "foobar"
  end
end
Run Code Online (Sandbox Code Playgroud)

随着extend方法被添加为类方法,并且可以直接在类对象本身上调用:

class Bar
  extend Foo
end

Bar.bar # => "foobar"
Run Code Online (Sandbox Code Playgroud)

或者,您可以在类范围之外调用它:

class Bar
end

Bar.extend Foo

Bar.bar # => "foobar"
Run Code Online (Sandbox Code Playgroud)

include略有不同.它将添加方法作为实例方法.它们只能在类的实例上调用:

class Bar
  include Foo
end

Bar.bar # NoMethodError
a = Bar.new
a.bar # => "foobar"
Run Code Online (Sandbox Code Playgroud)

关键的区别在于我们首先必须创建一个实例a,然后才能调用实例方法.

正如sepp2k所说,extend可以在任何Object上调用,而不仅仅是Class对象.例如,你可以去:

class Bar
end

a = Bar.new
a.extend Foo
a.bar # => "foobar"
Run Code Online (Sandbox Code Playgroud)

但是,bar只会添加到单个实例中a.如果我们创建一个新实例,您将无法调用它.

b = Bar.new
b.bar # => MethodNotFoundError
Run Code Online (Sandbox Code Playgroud)