开发者

Basic metaprogramming: extending an existing class using a module?

开发者 https://www.devze.com 2023-03-31 13:18 出处:网络
I\'d like part of my module to extend the String class. This doesn\'t work module MyModule class String

I'd like part of my module to extend the String class.

This doesn't work

module MyModule
  class String
    def exclaim
      self << "!!!!!"
    end
  end
end

include MyModule

string = "this is a string"
string.exclaim

#=> NoMethodError 

But this does

module MyModule
  def exclaim
    self << "!!!!!"
  end
end

class String
  include MyModule
end

string = "this is a string"
string.exclaim

#=> "this is a string!!!!!"

I don't want all the other functionality of MyModule to be marooned in String. Including it again开发者_开发技巧 at the highest level seems ugly. Surely there is a neater way of doing this?


The exclaim method in your first example is being defined inside a class called MyModule::String, which has nothing to do with the standard String class.

Inside your module, you can open the standard String class (in the global namespace) like this:

module MyModule
  class ::String
    # ‘Multiple exclamation marks,’ he went on, shaking his head,
    # ‘are a sure sign of a diseased mind.’ — Terry Pratchett, “Eric”
    def exclaim
      self << "!!!!"
    end
  end
end


I'm not sure I've understood your question but why don't open string in a file, say exclaim.rb, and then require it when you need it:

exclaim.rb

  class String
    def exclaim
      self << "!!!!!"
    end
  end

and then

require "exclaim"

"hello".exclaim

But maybe I'm missing something?

0

精彩评论

暂无评论...
验证码 换一张
取 消