Reputation: 575
Define a class as follows. I want to call one_method
dynamically. By default, wow.one_method
calls the first one_method
. If I want to change the behavior of the method, just call redefine
.
I can implement the method as a function type property, but that is not what I want.
If I use the following code directly, it would report errors. Could you modify it slightly.
class Wow
def one_method
puts "hello Ruby"
end
def redefine(what="none")
define_method :one_method do
puts what
end
end
end
wow = Wow.new
wow.redefine("Whatever I want.")
Upvotes: 0
Views: 66
Reputation: 83680
I would recommend achieving your goal in a more canonical way, just redefine the method on the instance itself:
class Wow
def one
:one
end
end
w = Wow.new
w.one
#=> :one
def w.one
:two
end
w.one
#=> :two
Drawbacks are:
Alternatives:
I don't know your real problem, but for your particular question it is better to parameterize your one_method
method just to receive an argument for puts
. Also, you can pass a block, so you will receive more grained control over the behavior.
Upvotes: 0
Reputation: 16012
You can achieve that via class_eval
or instance_eval
:
class Wow
def one_method
puts "hello Ruby"
end
def redefine(what="none")
self.class.class_eval do
define_method :one_method do
puts what
end
end
end
end
wow = Wow.new
wow.one_method #=> hello Ruby
wow.redefine("Whatever I want.")
wow.one_method #=> Whatever I want.
Reason is that define_method
defines instance method on the receiver and is a class's instance method so you'll have to call it on the eigen class of the object that you want to redefine a method on.
Upvotes: 1