模块中的实例变量?

Hom*_*ith 34 ruby module

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

module Stacklike
  def stack
    @stack ||= []
  end
end
Run Code Online (Sandbox Code Playgroud)

mcf*_*gan 44

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

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
Run Code Online (Sandbox Code Playgroud)

将输出"1"

  • 这真的是一个很好的设计吗?我的意思是,如果您在不知道其中包含模块的情况下包含模块,则可能会遇到变量被覆盖且出现各种问题的问题.特别是在模块需要一些变量来存储状态的情况下.是否有可能在模块中具有状态而不暴露它? (10认同)
  • 不,这不是好设计.但是当涉及模块和/或monkeypatching时,所有的赌注都是关闭的.毕竟,ruby程序的行为可以改变需要宝石的顺序,更不用说gem /应用程序中的各个模块正在做什么. (5认同)

Aru*_*hit 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
Run Code Online (Sandbox Code Playgroud)

输出:

"1.9.3"
[]
false
true
[:@stack]
Run Code Online (Sandbox Code Playgroud)

说明:是的,Module实例变量存在于class当你将include它们的类内.但是你可以看到,p a.instance_variable_defined?(:@stack)被显示false@stack尚未定义,直到一个.在B点,我定义了实例变量@stack.因此,在C点的陈述,输出为true.表示模块实例变量不是由模块本身创建的,但class如果class包含该模块,则可以由实例完成.在声明ë输出[]作为静止该点的实例变量没有定义,但是,如果你看到的线的输出d,证明的@stack是在对象内部aclass A.

为何如此设计?

这是设计或有时来自要求.假设您被要求编写一个堆栈操作代码,将由两家机票预订公司使用,Say AB.现在A是他们的客户服务的堆栈政策,但他们还有更多的手续.B公司也使用堆栈政策与自己的手续不同A.因此,在设计的情况下,Stack内部操作class Aclass B,更好的办法是把它写在一个共同的地方,因为这两个AB具有内他们共同的这个功能.在未来,如果另一家公司C来给你,你也可以使用该模块到他们的阶级,而无需重新编写每个相同的功能A,BC.可以有更多的想法,但希望这将帮助您回答问题的最后部分.

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

干杯!!


Cho*_*ett 5

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

class Lifo
  include Stacklike
end

l = Lifo.new
l.add_to_stack(:widget)
Run Code Online (Sandbox Code Playgroud)

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

  • 那么碰撞呢?如果在 Lifo 中我有一个 @stack 变量,那么优先考虑什么? (2认同)
  • 他们碰撞。`@stack` 既指的是 `Lifo` 中原生的那个,也指的是 `Stacklike` 中的那个。Pickaxe 建议不要给你的 mixin 任何状态;相反,要求任何包含它的东西都必须提供一个 `stack` 方法。在许多方面,带有状态的 mixin 不是 mixin。这是一个班级。 (2认同)