Reputation: 2696
In Ruby, is it possible to yield to a subclass method from a superclass method without affecting code in the subclass? I'm trying to avoid calling super
in the subclass.
class SuperClass
def do_something
puts "getting ready..."
# how to then yield back to the subclass do_something method?
puts "done."
end
end
class SubClass < SuperClass
def do_something
# how to first execute the superclass do_something method?
puts "doing something ..."
end
end
Desired functionality is to specifically call SubClass.do_something
and receive the following output:
"getting ready..."
"doing something..."
"done."
EDIT:
Maybe the real question is: How to DRY-up the code below, removing calls to self.get_ready
and self.finish_up
from all subclasses, using any ruby meta-programming technique that keeps those classes DRY:
class SuperClass
def self.get_ready
puts "getting ready ..."
end
def self.finish_up
puts "done."
end
end
class SubClassA < SuperClass
def self.do_something
self.get_ready
puts "doing something ..."
self.finish_up
end
end
class SubClassB < SuperClass
def self.do_something
self.get_ready
puts "doing something else, a little differently..."
self.finish_up
end
end
class SubClassC < SuperClass
def self.do_something
self.get_ready
puts "doing something crazy..."
self.finish_up
end
end
Upvotes: 3
Views: 2903
Reputation: 46193
If you're really not open to using super
, this is pretty much impossible.
With super
, it's pretty simple:
class SuperClass
def do_something
puts "getting ready..."
yield
puts "done."
end
end
class SubClass < SuperClass
def do_something
super.do_something do
puts "doing something..."
end
end
end
On the other hand, without using super
, this becomes simpler if you are open to multiple methods:
class SuperClass
def do_something
puts "getting ready..."
self.actually_do_the_thing
puts "done."
end
def actually_do_the_thing
raise NotImplementedError
end
end
class SubClass < SuperClass
def actually_do_the_thing
puts "doing something..."
end
end
Upvotes: 6
Reputation: 8424
In Practical Object-Oriented Design in Ruby, what Sandi Metz recommend you do to overcome calling super is to define a "hook" method in the super-class, which only job would be to get over-written by the child methods. In your case, you could do something like this:
class SuperClass
def self.do_something
puts "getting ready..."
do_something_child
puts "done."
end
def self.do_something_child; end
end
class SubClass < SuperClass
def self.do_something_child
puts "doing something ..."
end
end
SubClass.do_something
Upvotes: 8