Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby包含模块';s模型中的单一方法_Ruby_Methods_Module_Include - Fatal编程技术网

Ruby包含模块';s模型中的单一方法

Ruby包含模块';s模型中的单一方法,ruby,methods,module,include,Ruby,Methods,Module,Include,我有一个下面的模块 module SimpleTask def task1 end def task2 end def task3 end end 我有一个模型,它只需要模块SimpleTask的task2方法 我知道在我的模型中包含include SimpleTask可以完成这项工作 但我想知道我是否只能在我的模型中包含特定的task2方法。听起来您需要将#task2重构为一个单独的模块(例如,BaseTask)。然后,您可以轻松地只在只需要#

我有一个下面的模块

module SimpleTask
    def task1
    end
    def task2
    end
    def task3
    end
end
我有一个模型,它只需要模块
SimpleTask
task2
方法

我知道在我的模型中包含
include SimpleTask
可以完成这项工作


但我想知道我是否只能在我的模型中包含特定的
task2
方法。

听起来您需要将
#task2
重构为一个单独的模块(例如,
BaseTask
)。然后,您可以轻松地只在只需要
#task2
的位置包含
BaseTask

module BaseTask
  def task2
    ...
  end
end

module SimpleTask
  include BaseTask

  def task1
    ...
  end

  def task3
    ...
  end
end
如果没有更具体的问题(如
SimpleTask
方法之间的相互依赖性等),很难提供更多帮助

你可以做一些元编程,包括SimpleTask,然后取消定义你不想要的方法,但是在我看来,这很难看。

你可以添加

module SimpleTask
    def task1
    end
    def task2
    end
    def task3
    end
    module_function :task2
end
因此,您可以像调用模块上的类方法一样调用该方法,并将其作为实例 方法,即:

class Foo
   include SimpleTask
end #=> Foo.new.task2
class LessFoo
   def only_needs_the_one_method
      SimpleTask.task2
   end
end #=> LessFoo.new.only_needs_the_one_method
或者,如果模块中确实没有共享状态,并且您不介意总是使用模块名称本身,那么您可以像这样声明所有类级别的方法:

module SimpleTask
    def self.task1
    end
    def self.task2
    end
    def self.task3
    end
end

class Foo
   include SimpleTask # Does, more or less nothing now
   def do_something
     SimpleTask.task1
   end
end 
#=> Foo.new.task2 #=> "task2 not a method or variable in Foo"
#=> Foo.new.do_something does, however, work
class LessFoo
   def only_needs_the_one_method
      SimpleTask.task2
   end
end #=> LessFoo.new.only_needs_the_one_method works as well in this case

但在这种情况下,您必须更改所有呼叫者。

我将从中窃取一个示例,它限制了它所包含的内容

...
class Delegator < BasicObject
  kernel = ::Kernel.dup
  kernel.class_eval do
    [:to_s,:inspect,:=~,:!~,:===,:<=>,:eql?,:hash].each do |m|
      undef_method m
    end
  end
  include kernel
...
您可以随时将其翻转,使其变为“仅包含”,而不是“包含”


问题是,remove_方法不适用于嵌套模块,使用undef将阻止在整个层次结构中搜索该方法。

一个简单的解决方案是

define_方法:task2,SimpleTask.instance_方法(:task2)

可能重复的问题没有什么问题,这是一个好问题,而且非常清楚。我进入本页是因为我有完全相同的问题。我不想创建新模块,也不想不必要地在类命名空间中包含其他方法。我只想从模块中包含一个方法。
mo只要所有模块实例方法都是私有的,dule_函数就很好。如果您希望它们是公共的,可以使用
extend self
。必须注意的是,所有方法都不依赖于包含它们的实例的状态;在这种情况下,类方法将无法工作。
module PreciseInclude

  def include_except(mod, *except)
    the_module = mod.dup
    the_module.class_eval do
      except.each do |m|
        remove_method m # was undef_method, that prevents parent calls
      end
    end
    include the_module
  end
end

class Foo
  extend PreciseInclude

  include_except(SimpleTask, :task1, :task2)
end

Foo.instance_methods.grep(/task/) => [:task3]