If you really just want to pretty this sort of thing up,
why not wrap all your methods in a class like so:
# a container to store all your methods you want to use a hash to access
class MethodHash
alias [] send
def one
puts "I'm one"
end
def two
puts "I'm two"
end
end
x = MethodHash.new
x[:one] # prints "I'm one"
x.two # prints "I'm one"
or, to use your example:
# a general purpose object that transforms a hash into calls on methods of some given object
class DelegateHash
def initialize(target, method_hash)
@target = target
@method_hash = method_hash.dup
end
def [](k)
@target.send(@method_hash[k])
end
end
class A
def initialize
@a = DelegateHash.new(self, { 0 => :a })
end
def a()
puts "hello world"
end
def b()
@a[0]
end
end
x = A.new
x.a #=> prints "hello world"
x.b #=> prints "hello world"
One other basic error that you made is that you initialized @a
outside of any instance method -
just bare inside of the definition of A
. This is a big time no-no, because it just doesn't work.
Remember, in ruby, everything is an object, including classes, and the @
prefix means the instance
variable of whatever object is currently self. Inside an instance method definitions, self
is an instance
of the class. But outside of that, just inside the class definition, self
is the class object - so you defined
an instance variable named @a
for the class object A
, which none of the instances of A
can get to directly.
Ruby does have a reason for this behaviour (class instance variables can be really handy if you know what
you're doing), but this is a more advanced technique.
In short, only initialize instance variables in the initialize
method.