tel*_*all 5 ruby extension-methods
这个问题有两个部分.
在Ruby Programming Language一书中,有一个使用模块扩展字符串对象和类的示例(第8.1.1节).
第一个问题.为什么如果使用新方法扩展类,然后创建该类的对象/实例,则无法访问该方法?
irb(main):001:0> module Greeter; def ciao; "Ciao!"; end; end
=> nil
irb(main):002:0> String.extend(Greeter)
=> String
irb(main):003:0> String.ciao
=> "Ciao!"
irb(main):004:0> x = "foo bar"
=> "foo bar"
irb(main):005:0> x.ciao
NoMethodError: undefined method `ciao' for "foo bar":String
from (irb):5
from :0
irb(main):006:0>
Run Code Online (Sandbox Code Playgroud)
第二部分,当我尝试扩展Fixnum对象时,我得到一个未定义的方法错误.有人可以解释为什么这适用于字符串而不是fixnum?
irb(main):045:0> module Greeter; def ciao; "Ciao!"; end; end
=> nil
irb(main):006:0> 3.extend(Greeter)
TypeError: can't define singleton
from (irb):6:in `extend_object'
from (irb):6:in `extend'
from (irb):6
Run Code Online (Sandbox Code Playgroud)
第一个问题.为什么如果使用新方法扩展类,然后创建该类的对象/实例,则无法访问该方法?
因为你扩展了String类,所以#ciao是一个类方法而不是实例方法.
String.send(:include, Greeter)
x = "foo bar"
x.ciao
# => "Ciao!"
Run Code Online (Sandbox Code Playgroud)
第二部分,当我尝试扩展Fixnum对象时,我得到一个未定义的方法错误.有人可以解释为什么这适用于字符串而不是fixnum?
这是简短的回答.
"Fixnums,Symbols,true,nil和false被实现为立即值.对于立即值,变量保存对象本身,而不是对它们的引用.
不能为这些对象定义单例方法.具有相同值的两个Fixnum总是表示相同的对象实例,因此(例如)Fixnum的实例变量与值"one"在所有"ones"之间共享是系统.这使得无法为其中一个定义单例方法."
当然,您可以包含/扩展Fixnum类,每个Fixnum实例都会公开Mixin中的方法.这正是Rails/ActiveSupport为了允许您编写而执行的操作
3.days.ago
1.hour.from_now
Run Code Online (Sandbox Code Playgroud)