-
-
Save saturnflyer/201506ee3f1aa74fa7642d35ede732aa to your computer and use it in GitHub Desktop.
Given the below hierarchy how many ways can you think of to wrap the `Parent#foo` implementation so that `Grandchild1` and `Grandchild2` can have their own unique logic that executes after all of the mixin `foo`(s) but before the `Parent#foo` executes?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module N | |
def foo | |
puts "N: foo" | |
super | |
end | |
end | |
module O | |
def foo | |
puts "O: foo" | |
super | |
end | |
end | |
class Parent | |
def foo | |
puts "foo" | |
end | |
end | |
class Child < Parent | |
include N | |
end | |
module FooChecker | |
def self.from(klass) | |
special_foo_name = "#{klass.name}SpecialFoo" | |
mod = Module.new | |
self.const_set(special_foo_name, mod) | |
mod.class_eval %{ | |
def foo | |
if self.is_a?(#{klass.name}) | |
puts %{#\{self.class.name\} special foo} | |
end | |
super | |
end | |
} | |
# Altenatively this. But super must be called | |
# with explicit arguments when used in define_method | |
# mod.class_eval do | |
# define_method :foo do | |
# if self.is_a?(klass) | |
# puts %{#{self.class.name} special foo} | |
# end | |
# super() | |
# end | |
# end | |
mod | |
end | |
end | |
class Grandchild1 < Child | |
Parent.prepend(FooChecker.from(self)) | |
include O | |
end | |
class Grandchild2 < Child | |
Parent.prepend(FooChecker.from(self)) | |
include O | |
end | |
# Say we want this to wrap the this to output: | |
# O: foo | |
# N: foo | |
# Grandchild1 special foo | |
# foo | |
Grandchild1.new.foo | |
# And we wanted this to output: | |
# O: foo | |
# N: foo | |
# Grandchild2 special foo | |
# foo | |
Grandchild2.new.foo |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment