Instance variables in modules?

后端 未结 4 582
一向
一向 2020-12-29 19:03

How is it possible that I can have instance variables in a module even though I cannot create an instance of the module? What would be the purpose of @stack in

相关标签:
4条回答
  • 2020-12-29 19:38

    See the below:

    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
    

    Output:

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

    Explanation: Yes, Module instance variables are present in the class when you would include them inside the class. But you can see that p a.instance_variable_defined?(:@stack) is showing false as @stack is still not defined till A. At point B I defined the instance variable @stack. Thus statement in point C, outputs as true. Means module instance variables are not being created by the module itself,but that can be done by the class instances if the class included that module. Statement in E outputs [] as still that point the instance variable was not defined, but if you see the output for the line D, it is proved the @stack is inside the object a of class A.

    Why such design?

    This is the design or sometimes come from the requirements. Say you have been asked to write a stack operation code which will be used by two ticket booking companies,Say A and B. Now A are stack policy for their customers to serve but also they have any more formalities with that. B company also using stack policy with their own formalities which is different from A. Thus in case of designing Stack operation inside class A and class B, better idea to write it in a common place,as Both A and B have this functionality common within them. In future if another company C comes to you you can also use that module into their class, without rewriting the same functionality for each A,B and C. There can be more thoughts but hope this will help you to answer your self for your last part of the questions.

    That's all about the concept. Hope it helps.

    Cheers!!

    0 讨论(0)
  • 2020-12-29 19:40

    When you include a module in a class, all of its instance methods are effectively "pasted in" to the host class. So if you have:

    class Lifo
      include Stacklike
    end
    
    l = Lifo.new
    l.add_to_stack(:widget)
    

    Then l now has an instance variable @stack, brought in from Stacklike.

    0 讨论(0)
  • 2020-12-29 19:44

    When you include the module Stacklike in some other class that instance variable will be available as if it was defined in that class. That give you the option to set and handle instance variables of the base class from the module itself.

    0 讨论(0)
  • 2020-12-29 19:47

    Think of the instance variable as something which will exist in any class that includes your module, and things make a bit more sense:

    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
    

    will output "1"

    0 讨论(0)
提交回复
热议问题