11
module X
end

module Y
end

module Z
  #TODO include X replacement of including Y
  #TODO include Y replacement of including X
end

有没有办法解决 ruby​​ 不包含 uninclude 关键字的事实?

4

4 回答 4

7

如果你真的需要这种功能,你可以通过使用细化来实现。

class Foo
end

module X
  def x
    puts 'x'
  end
end

module Y
end

module R
  refine Foo do
    include X
    include Y
  end
end

# In a separate file or class
using R
# Foo now includes X and Y
Foo.new.x

# In a different file or class
# Foo no longer includes X and Y
Foo.new.x # NoMethodError
于 2013-10-19T05:31:57.333 回答
1

真正的答案是,在 Ruby 中,无论是 1.x 还是 2.x,一旦包含一个模块,就无法取消包含但我知道有人在某处编写了允许不包含模块的 Ruby 扩展。

编辑:好的,实际上,OP 是 Ruby 包含的对立面的副本,所以根据@eliahbanister的回答,有问题的库是https://github.com/yrashk/rbmodexclhttps://github.com/banister/mixology19

于 2013-10-19T07:32:11.427 回答
0

我对此不太满意,但如果两个模块包含相同的方法名称,它确实有效。

文件 c.rb

module A
  def me
    puts "I am C"
  end
  def whosit?
    puts "It's me, Becky"
  end
end

文件 d.rb

module A
  def me
    puts "I am D"
  end
end

然后

class X
  load('c.rb')
  include A
end

x = X.new

x.me # => I am C
x.whosit? # => It's me, Becky
load('d.rb')
x.me # => I am D
x.whosit? # => It's me, Becky !! Unwanted !!
load('c.rb')
x.me # => I am C

load()只是打开模块 A 并更改和/或添加代码;它没有触及的东西仍然存在。 load()不是真正的明亮。我认为eval()如果它多次加载同一个文件,它基本上会做一个并且可能不在乎。

要使用它,不要同时使用requirec.rb 或 d.rb。

编辑:在之前的编辑中,我添加了一个关于require_relative. 回想起来,我发现它既不相关也不有趣,所以不以为然。

于 2013-10-19T05:49:45.630 回答
0

如果您想创建一个可以动态选择是否包含模块的类,您可以通过在初始化期间将模块包含在单例类中来实现。

这不会让你得到与在一个对象的单例类中“取消包含”模块相同的东西,同时保持包含在类本身中(这是我想到的uninclude),但它可能与上面的细化解决方案的某些特性相匹配(具有相同的问题)如果这会激发您的一些想法,请使用不同的模式。

module A
  def hi; :hi; end
end

class Foo
  def initialize(include_a = true)
    singleton_class.include(A) if include_a
  end
end

Foo.new.hi
# => :hi

Foo.new(false).hi
# NoMethodError: undefined method `hi' for #<Foo:0x00007fe19a973f00>

了解这是一个老问题,但是如果您正在寻找uninclude功能,那么值得真正考虑一下您到底想用它做什么 - 像“动态包含”这样的东西就足够了吗?

于 2019-06-07T18:10:29.213 回答