43

即使我无法创建模块的实例,我怎么可能在模块中拥有实例变量?@stack下面的模块的目的是Stacklike什么?

module Stacklike
  def stack
    @stack ||= []
  end
end
4

4 回答 4

50

将实例变量想象成任何包含您的模块的类中都会存在的东西,事情就更有意义了:

module Stacklike
  def stack
    @stack ||= []
  end

  def add_to_stack(obj)
    stack.push(obj)
  end

  def take_from_stack
    stack.pop
  end
end

class ClownStack
  include Stacklike

  def size
    @stack.length
  end
end

cs = ClownStack.new
cs.add_to_stack(1)
puts cs.size

将输出“1”

于 2013-03-18T14:17:23.820 回答
17

见下文:

p RUBY_VERSION
module Stacklike
  def stack
    @stack ||= []
  end

  def add_to_stack(obj)
    stack.push(obj)
  end

  def take_from_stack
    stack.pop
  end
end

class A
include Stacklike
end

a = A.new
p a.instance_variables #<~~ E
p a.instance_variable_defined?(:@stack) #<~~ A
a.add_to_stack(10) #<~~ B
p a.instance_variable_defined?(:@stack) #<~~ C
p a.instance_variables #<~~ D

输出:

"1.9.3"
[]
false
true
[:@stack]

解释:是的,Module实例变量存在于类中classinclude但是您可以看到它p a.instance_variable_defined?(:@stack)显示false为直到A@stack仍未定义。在B点,我定义了实例变量@stack。因此C点中的语句输出为。意味着模块实例变量不是由模块本身创建的,但如果包含该模块,则可以由实例完成。E中的语句仍输出为未定义实例变量的那一点,但是如果您看到D行的输出,则证明trueclassclass[]@stack在 的对象aclass A

为什么会有这样的设计?

这是设计或有时来自要求。假设您被要求编写一个堆栈操作代码,将被两家订票公司使用,SayAB。现在A是为他们的客户服务的堆栈政策,但他们也有更多的手续。B公司也使用堆栈策略与他们自己的手续不同A。因此,如果在内部设计操作Stack,最好将其写在一个共同的地方,就像两者一样,并且在它们内部具有共同的功能。将来,如果另一家公司来找您,您也可以将该模块用于他们的课程,而无需为每个 重写相同的功能,并且class Aclass BABCABC. 可以有更多的想法,但希望这会帮助你回答你自己的最后一部分问题。

这就是概念。希望能帮助到你。

干杯!!

于 2013-03-18T14:18:57.377 回答
5

当您在一个类中包含一个模块时,它的所有实例方法都会有效地“粘贴”到宿主类中。因此,如果您有:

class Lifo
  include Stacklike
end

l = Lifo.new
l.add_to_stack(:widget)

然后l现在有一个实例变量@stack,从Stacklike.

于 2013-03-18T14:18:00.140 回答
4

当您在某个其他类中包含模块 Stacklike 时,该实例变量将可用,就好像它是在该类中定义的一样。这使您可以选择从模块本身设置和处理基类的实例变量。

于 2013-03-18T14:18:14.707 回答