给定的
module Foo
def bar
puts "foobar"
end
end我能做到
String.extend(Foo)其结果就是
String.bar # => "foobar"为什么这个不起作用?:
a = String.new
a.bar # => NoMethodError: undefined method `bar' for "":String是不是因为'a‘现在是实例,而.extend只对类方法起作用?为什么它会失去我通过.extend赋予字符串的‘新’功能?
发布于 2011-12-15 06:04:38
Ruby允许以两种方式将模块中的方法添加到类中:extend和include。
使用您提供的模块:
module Foo
def bar
puts "foobar"
end
end使用extend,这些方法被添加为类方法,并且可以直接在类对象本身上调用:
class Bar
extend Foo
end
Bar.bar # => "foobar"或者,您可以在类范围之外调用它:
class Bar
end
Bar.extend Foo
Bar.bar # => "foobar"include稍有不同。它将添加这些方法作为实例方法。它们只能在类的实例上调用:
class Bar
include Foo
end
Bar.bar # NoMethodError
a = Bar.new
a.bar # => "foobar"关键区别在于,我们首先必须创建一个实例a,然后才能调用该实例方法。
正如sepp2k所指出的,extend可以在任何对象上调用,而不仅仅是类对象。例如,您可以这样做:
class Bar
end
a = Bar.new
a.extend Foo
a.bar # => "foobar"但是,只会将bar添加到单实例a。如果我们创建了一个新实例,您将无法调用它。
b = Bar.new
b.bar # => MethodNotFoundError发布于 2011-12-15 06:02:52
在Ruby语言中,String类是一个对象,通过执行String.extend( Foo ),您可以为String类对象创建一个单例类,并在其中包含模块Foo(这意味着您正在向String类对象添加类方法,因此可以调用String.bar)。句号。
a.bar无法工作,因为没有实例方法栏。
不,您还没有通过扩展将new赋给String。
发布于 2011-12-15 06:03:03
Object#extend方法将参数模块定义的方法添加到接收器。
您必须记住,扩展类本身就是一个对象(类型为Class),因此当您使用它作为接收器调用“String”时,该类对象(String)本身就会获得新方法。
因此,在您的第一个示例String.extend(Foo)中,将函数"bar“添加到String类实例。也就是说,“String”现在是阴影类(又称单例类)的一个实例方法,因此对象String(它是一个类)现在具有方法"bar“。这与向String类添加类方法(例如def String.bar; puts 'foobar'; end)具有大致相同的效果,因此它对String类型的实例没有影响。
https://stackoverflow.com/questions/8512089
复制相似问题