Ruby Module Variables
-
Based on the reference: Module Variables, I figured that it's valid to create instance variables inside the Module. I tested it on SU via Ruby and it all worked, without any conserns. Though, some of Ruby things began bugging me, and thus I need a good confirmination.
1st: Creating instance variables in module namespace is valid, though is it right and why?
2nd: Since, you can't create an instance of a module (SomeModule.new = No function such as new) then, why are there things such as module instance methods (def someMethod) and module class methods (def self.someMethod)?
3rd: Getting even deeper, I figured that it is valid to create constants inside the class. They act the same way as class variables, though as usual ruby would warn once the constant is assigned a different value. So, is it also right to initiate constants inside the class namespace?
4th: What is a difference bettween instance variables and class variables in the module?
-
@anton_s said:
2nd: Since, you can't create an instance of a module (SomeModule.new = No function such as new)...
WRONG
class
Module
, like ALL Ruby objects, has a new() constructor class method (which is a block form method,) ie:Anton = Module.new() { @color = blue def self.get_color() @color end }
Remember that a Ruby script is for humans to read.. Ruby does not really use it. The interpreter reads the script "
module Anton
" and translates it into a constructor call (similar to the above example,) but in C code.@anton_s said:
... then, why are there things such as module instance methods (def someMethod) and module class methods (def self.someMethod)?
Because modules can be the library type (best used with module/class variables and module/class methods,) OR the "Mixin" type, which are used to mixin instance variables and instance methods into custom classes. (You can also create a hybrid that is both types, like the
Math
module is.)
So.. read up on Mixin Modules. -
Great questions, Anton.
Around here modules are used mainly as namespaces to wrap methods and avoid method name conflicts. More typically in ruby, modules are used to implement the object-oriented programming concept called multiple inheritance (called mixins in Ruby.)
As far as I know, a instance variable, a class variable, and a constant will all have the same visibility (scope) when defined at the top-level of a module. They will all be visible everywhere within the module namespace, including classes and other modules defined within the module. A unique feature of Ruby is that these same objects (classes, modules, variables) are visible across files if the files use the same names.
Which is "right" may come down to convention and personal preference.
-
@anton_s said:
3rd: Getting even deeper, I figured that it is valid to create constants inside the class. They act the same way as class variables, though as usual ruby would warn once the constant is assigned a different value. So, is it also right to initiate constants inside the class namespace?
YES you may. But do not use Constants in place of variables. (At some time in the future the Core guys are not going to let us change them.)
To prevent the warning (say during debugging... wrap Constant definitions within a "Run Once" conditional.
unless file_loaded?(__FILE__) DELIMITER = "," RECORD_END = "\n" end
or:
DELIMITER = "," unless defined?(DELIMITER)
or
DELIMITER ||= ","
If you really must change a Constant, you can use the
remove_constant(:CONSTANTNAME)
private method within your namespace first, then redefine it.. and there will be no warning output. -
@anton_s said:
1st: Creating instance variables in module namespace is valid, though is it right and why?
What Jim says is true.. personal preference.. but I will usually advise using module variables for library modules and namespaces, and save instance variables for mixin modules and classes.
But Ruby is designed to be multi-paradigm, so you can do things in the way you feel most comfortable.
@anton_s said:
4th: What is a difference bettween instance variables and class variables in the module?
In modules, it's subtle.
If you use a proxy class block within your module (which makes things A WHOLE LOT EASIER...) then Constants and module variables need to be defined outside the proxy class block, but instance variables need to be defined within it:
require('sketchup.rb') module Anton;;FancyPlugin unless file_loaded?(File.basename(__FILE__)) # Constants Border = "blue" # Module Vars @@opts = {} end class << self # PROXY CLASS # INSTANCE VARS @counter = 0 @limit = 100 @@opts[;limit]= @limit def set_limit(arg=100) if arg.is_a?(Numeric) @limit = arg.to_i @@opts[;limit]=@limit end end end # PROXY CLASS # We can call methods in the proxy class # from inside module without qualification; set_limit(99) file_loaded(File.basename(__FILE__)) end # module Anton;;FancyPlugin # We can call methods in the proxy class # from outside the module WITH qualification; Anton;;FancyPlugin.set_limit(125)
-
Thanks, for a great replie(s) Dan and Jim
Well, isn't this:
@dan rathbun said:
> Anton = Module.new() { > @color = 'blue' > def self.get_color() > @color > end > } >
the same as this:?
module Anton @color = 'blue' def self.get_color() @color end end
I don't see any difference in these
@dan rathbun said:
Because modules can be the library type (best used with module/class variables and module/class methods,) OR the "Mixin" type, which are used to mixin instance variables and instance methods into custom classes. (You can also create a hybrid that is both types, like the
Math
module is.)
So.. read up on Mixin Modules.Found a really good explanation here, thanks
-
@jim said:
As far as I know, a instance variable, a class variable, and a constant will all have the same visibility (scope) when defined at the top-level of a module. They will all be visible everywhere within the module namespace, including classes and other modules defined within the module. A unique feature of Ruby is that these same objects (classes, modules, variables) are visible across files if the files use the same names.
Which is "right" may come down to convention and personal preference.
Alright, so are the two namespaces below right and which of them do you prefer better:?
module CandiesM @@count ||= 0 def self.buy(); @@count += 1; end end class CandiesC @@count ||= 0 def self.buy(); @@count += 1; end end
-
@anton_s said:
I don't see any difference in these
No kidding! That was exactly the point I was making.
-
@anton_s said:
Alright, so are the two namespaces below right and which of them do you prefer better:?
This:
module Anton module CandiesM @@count ||= 0 def self.buy(); @@count += 1; end end class CandiesC @@count ||= 0 def self.buy(); @@count += 1; end end end # module Anton
All of your modules and/or classes need to be within your "author" namespace.
If you need one copy of some code, make it a module.
If you need multiple copies of some code, make it a class, and use multiple instances of the code. -
@dan rathbun said:
All of your modules and/or classes need to be within your "author" namespace.
If you need one copy of some code, make it a module.
If you need multiple copies of some code, make it a class, and use multiple instances of the code.Ok, good advice, thaks
. Now I'm on my way to 'Keep on typing' the code.
Advertisement