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
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
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
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