Hi. I have big module with many tiny methods. These methods all return a string. Example: module Foo def one(i = '') return '<'+i+'>' end def two(i = '') return '<'+i+i+'>' end end So far so good. Please note that this is just a short demo, a simplification. The real module is huge, and much more complicated. But I just want to demo something relevant for my question. Now, I include this module into class bar. class Bar include Foo attr_reader :string def initialize @string = '' build_string end def build_string @string << one('hello') @string << two('world') end end x = Bar.new x.string Ok this will return this string: "<hello><worldworld>" So far, everything works correctly. As you can see, in class Bar I can use an @ivar, in this case @string. Now, however, I _also_ want to be able to store this in the module. But how can I do this? I could use a global variable, but this is awful. I could use a constant, like X = [''] and append to that in the module, but this is also awful. Why would I want this? Because a module is more flexible than a class - I can use the module to mix it into other classes AND I could use the module standalone. When I would use a class alone, I could no longer mix it into other classes. I could only subclass, but subclass mandates and enforces a strict hierarchy, which I really do not want or need in ALL my uses cases, so I am stuck keeping this as a module. Help!!! Any suggestion for how to store this information in the module additionally? I want to have the module give me back the current version of the string it uses (internally). And I also must keep the core functionality of including all those methods in the module into my new, more specialized classes. Any HELPFUL suggestions welcome!
on 2013-02-03 10:12
on 2013-02-03 10:44
Subject: Storing string-data in a module Date: dom 03 feb 13 06:12:20 +0900 Quoting Marc Heiler (firstname.lastname@example.org): > Now, however, I _also_ want to be able to store > this in the module. But how can I do this? I might be mistaken, but I believe you cannot. There are global variables (prepended by '$'), class variables (prepended by '@@') and instance variables (prepended by '@'). But there are, to my knowledge, no module variables. And this is exactly why modules are more flexible: they provide methods, but they do not provide instantiation or storage. From what I know, a module can only own constants (immutable). I believe this boils down to the usual multiple-inheritance-related class of FAQ's. IMO, Ruby's designers have decided to avoid multiple inheritance not because it is evil, but because the sheer amount of unescapable, tangled complexity brought in *at language implementation level* by multiple inheritance would produce a clumsier language as a whole. I back their decision single-heartedly. If I were facing your problem, I would pass the string as the first parameter to all functions in the module, like this: def one(string,i='') string+='<'+i+'>' end You can directly use the instance's variable, like this: def one(i = '') @string+='<'+i+'>' end @string would be owned by the instance of each class that included your module. But I think this last way obfuscates things a bit too much. Carlo
on 2013-02-04 09:25
On Sun, Feb 3, 2013 at 3:43 AM, Carlo E. Prelz <email@example.com> wrote: > You can directly use the instance's variable, like this: > > def one(i = '') > @string+='<'+i+'>' > end > > @string would be owned by the instance of each class that included > your module. But I think this last way obfuscates things a bit too > much. *Much* agreed -- this would result in, effectively, a side-effect, or action at a distance, and create a coupling with the including class that may come back to bite one.