Открытые занятия в модуле - PullRequest
4 голосов
/ 16 апреля 2011

Я знаю, что могу выполнить следующее, чтобы добавить методы в класс String

class String
  def do_something
    puts self.size
  end
end

var = "test"
var.do_something

, и это вернет 4

Я хочу иметь модуль сфункция, которая принимает строку, но может вызывать метод do_something для этой строки (см., например, ниже) - возможно ли это?

РЕДАКТИРОВАТЬ: Добавлен пример кода, который не работает

module TestModule
  class String
    def do_something
      puts self.size
    end
  end

  def self.test(str)    
    str.do_something
  end
end

Это дает ошибку: undefined method 'do_something' for "hello":String (NoMethodError)

Ответы [ 2 ]

8 голосов
/ 16 апреля 2011

При написании кода вы определяете новый класс с именем TestModule :: String.Если вы хотите изменить встроенный класс Ruby String, вам нужно использовать полное имя String (с "" :: "), если вы хотите сохранить объявление внутри модуля.

module TestModule
  class ::String
    def do_something
      puts self.size
    end
  end

  def self.test(str)  
    str.do_something
  end
end

Добавление "::" говорит Ruby, что требуемый класс String не является частью TestModule.

Возможно, будет проще объявить String вне TestModule в том же файле.

Если вы не хотите загрязнять глобальный класс String, вы можете просто изменить конкретный экземпляр String, к которому вы хотите добавить метод.

module TestModule
  def self.test(str)  
    do_somethingify!(str)
    str.do_something
  end

  def self.do_somethingify!(str)
    unless str.respond_to? :do_something
      str.instance_eval do
        def do_something
          puts size
        end
      end
    end
  end      
end          
3 голосов
/ 16 апреля 2011

Может быть, это?

module TestModule
  module_function
  def test(str)
    str.instance_eval{doSomething}
  end
end

Test.test(str)

Редактировать Изменено из-за изменения в вопросе

Просто поместите определение doSomething вне TestModuleкласс.

class String
  def doSomething
    puts size
  end
end

module TestModule
  module_function
  def test(str)  
    str.doSomething
  end
end
...