模块中的实例变量?

时间:2013-03-18 14:04:19

标签: ruby module

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

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

4 个答案:

答案 0 :(得分:43)

将实例变量视为包含模块的任何类中存在的东西,事情更有意义:

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”

答案 1 :(得分:13)

见下文:

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实例变量出现在class,当你在课堂上include时。但是,您可以看到p a.instance_variable_defined?(:@stack)显示false@stack仍未定义,直到 A 。在 B 点,我定义了实例变量@stack。因此,语句 C ,输出为true。表示模块实例变量不是由模块本身创建的,但如果class包含该模块,则可以由class实例完成。 E 输出[]中的语句仍然没有定义实例变量,但如果您看到 D 行的输出,则证明{ {1}}位于@stack的对象a内。

为何选择此类设计?

这是设计或有时来自要求。假设您被要求编写一个堆栈操作代码,将由两个预订公司使用,说class AA。现在B是他们的客户服务的堆栈政策,但他们还有更多的手续。 A公司也使用堆栈策略,其自己的手续与B不同。因此,如果在AStack内设计class A操作,最好将其写在一个公共位置,因为class BA都具有此功能他们之间很常见。将来如果有另一家公司B来到您这里,您也可以将该模块用于他们的课程,而无需为每个CAB重写相同的功能。可以有更多的想法,但希望这将有助于你回答你自己的最后一部分问题。

这就是概念。希望它有所帮助。

干杯!!

答案 2 :(得分:5)

当您在类中包含模块时,其所有实例方法都会有效地“粘贴”到主机类中。所以如果你有:

class Lifo
  include Stacklike
end

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

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

答案 3 :(得分:3)

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