I was wondering how to access a global function fn
in ruby from a class which also defined a method fn
. I have made a workaround by aliasing the function like so:
def fn end class Bar alias global_fn fn def fn # how to access the global fn here without the alias global_fn end end
I'm looking for something along the lines of c++'s :: to access global scope but I can't seem to locate any information about it. I guess I don't know specifically what I'm looking for.
However, the use of global variables is often considered "un-Ruby," and you will rarely see them. Global variables are defined and used like any other variable. To define them, simply assign a value to them and begin using them. But, as their name suggests, assigning to global variables from any point in the program has global implications.
For instance, it is useful for keeping a GUI display up to date. There is a collection of special variables whose names consist of a dollar sign ( $) followed by a single character. For example, $$ contains the process id of the ruby interpreter, and is read-only.
Variable scope in Ruby is controlled by sigils to some degree. Variables starting with $ are global, variables with @ are instance variables, @@ means class variables, and names starting with a capital letter are constants. All other variables are locals.
Without a specific prefix for globals, given a statement pointNew = offset + point inside your draw method then offset refers to a local variable inside the method (and results in a NameError in this case). The same for @ used to refer to instance variables and @@ for class variables.
At the top-level a def
adds a private method to Object
.
I can think of three ways to get the top-level function:
(1) Use send
to invoke the private method on Object
itself (only works if the method is not a mutator since Object
will be the receiver)
Object.send(:fn)
(2) Get a Method
instance of the top-level method and bind it to the instance you want to invoke it on:
class Bar
def fn
Object.instance_method(:fn).bind(self).call
end
end
(3) Use super
(assumes no super classes of Bar
below Object
redefine the function)
class Bar
def fn
super
end
end
UPDATE:
Since solution (2) is the preferable one (in my opinion) we can try to improve the syntax by defining a utility method on Object
called super_method
:
class Object
def super_method(base, meth, *args, &block)
if !self.kind_of?(base)
raise ArgumentError, "#{base} is not a superclass of #{self}"
end
base.instance_method(meth).bind(self).call(*args, &block)
end
end
Use like the following:
class Bar
def fn
super_method Object, :fn
end
end
Where the first argument to super_method
must be a valid superclass of Bar
, the second argument the method you want to invoke, and all remaining arguments (if any) are passed along as parameters to the selected method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With