How does one - without inheritance - override a class method and call the original from within the new method?
This is kinda hard to get your head around sometimes, but you need to open the "eigenclass" which is the singleton associated with a specific class object. the syntax for this is class << self do...end.
class Time
alias :old_strftime :strftime
def strftime
puts "got here"
old_strftime
end
end
class Time
class << self
alias :old_now :now
def now
puts "got here too"
old_now
end
end
end
t = Time.now
puts t.strftime
Python. Override a method without creating a derived class and call the original method
You don't use inheritance. What you do is called monky patching!
So you can do the following:
ModuleB.py
from ModuleA import FooClass
# Preserve the original function:
FooClass.originalFooMethode = FooClass.fooMethode
def _newFooMethod(self):
if(not hasAttr(self,"varA "):
self.varA = 0
#Do some checks with varA
#CALL ORIGINAL fooMethod
self.originalFooMethode()
FooClass.fooMethod = _newFooMethod
Is it possible to call an overridden method in an instance of child class ES 2015?
It's JavaScript, so you can. There's no classes anyway, just prototypal inheritance with some syntactic sugar over it.
Which one do you want to call: Car
's emitsCarbon
specifically? That'll be
Car.prototype.emitsCarbon.call(car1);
Your object's class' direct ancestor class' emitsCarbon
in general?
car1.__proto__.__proto__.emitsCarbon.call(car1);
(You're not supposed to directly access __proto__
, but there's nothing actually stopping you besides the general good practice and guidelines).
Also, hybrids do emit carbon. Just a side note.
If I override a class method, is there a way I can call the original method (the one that was overridden)?
I present you with three icky ways to do this in +(void)load
. In every case, name your method MyCategory_method or so.
- class_getMethodImplementation() and class_replaceMethod(). Store the old IMP, and call it directly. You need to get the method's type encoding. Note that you can just use a normal C function too...
- class_getInstanceMethod(), method_getImplementation(), method_setImplementation(). As above, but you don't need to get the method's type encoding.
- class_getInstanceMethod() on both methods, and then method_exchangeImplementations(). Call MyCategory_method to get the original implementation. This is the easiest way to do it.
Sometimes, it's the only reasonably easy way to make it do what you want...
EDIT: And only do this if you know what you're doing!
How to override an inherited method from within another inherited class
That's a simultaneously fun and annoying problem to have! :) I believe that one of the missing links here is this:
- The
override
modifier is related tovirtual
orabstract
methods; a method with anoverride
modifier simply provides an alternative implementation to an existingvirtual
orabstract
method. Avirtual
method has a default implementation, anabstract
method has no implementation at all. - The
new
modifier however can be applied to any method and simply allows the reuse of a name that was already taken. These methods are not related to each other at all, the only similarity being that they forcibly share the same name.
The problem with new
is that the type using a new
method "pretends" that the original implementation never existed. The base class however is absolutely unaware of this - new
severs the link in the hierarchy, and this is what's casing your problem.
Generally speaking, you do not want to use the new
modifier.
That, and you probably wanted to use var m = new Program();
instead - reasons being explained below.
Consider these two pieces of code:
LogThings a = new DoMath();
a.WriteLog("something");
and
LogThings a = new Program();
a.WriteLog("something");
At this point, the method being called is LogThings.WriteLog()
. Even though we instantiate a DoMath
or Program
class that provides a new
method, the LogThings
part of the world doesn't "know" that. It instead believes to have a virtual
method that doesn't happen to be overridden. As a result, this code prints:
This is the base in LogThings something
As mentioned above: new
severs that link.
In the next example, the method being called is indeed DoMath.WriteLog()
, because we're now simply instantiating the DoMath()
class and call its LogThings
method.
DoMath b = new DoMath();
b.WriteLog("something");
Not surprisingly, this code prints
this is overriding the base in DoMath
This is the base in LogThings something
Note that it does not print "this is not overriding" because we did not instantiate an instance of the Program
class. Likewise, the base.LogThings()
call has nothing to do with "overriding", it simply changes the focus to the LogThings
type and calls whatever implementation it knows.
This is similar to the original code you used:
var m = new DoMath();
Lastly, consider this version:
DoMath c = new Program();
c.WriteLog("something");
Here, the Program
class actually overrides
the virtual void WriteLog
method of DoMath
. Consequently, this code prints
this is not overriding.
... which is now wrong, because it does.
The key to understanding this is that each class containing virtual or abstract methods has what's called a virtual function table, or vtable. This vtable is "inherited" by derived classes and allows the compiler to know which implementation of a method to call (through a so-called virtual dispatch).
You can consider an entry in the vtable to be something like a pointer to the actual implementation of a method (the one from the current class), followed by a pointer to the previous implementation.
In your example of DoMath
and Program
, instantiating the DoMath
class would produce a vtable consisting of only
DoMath.WriteLog(string) -> null
whereas instantiating the Program
class would produce an entry like this:
Program.WriteLog(string) -> DoMath.WriteLog(string) -> null
This is why ((DoMath)new Program()).WriteLog()
works - even though we look at a DoMath
reference, the compiler looks up the vtable for the instantiated type (Program
) and can follow the chain up to the actual implementation (Program.WriteLog
).
Do however note the makeshift null
in there. Because the DoMath
class declares the WriteLog
method as new
, it is considered to be a - well - new method, which is unrelated to the one from LogThings
. For LogThings
, the vtable world still looks somewhat like this:
LogThings.WriteLog(string) -> null
Because there is no legit override
- just a different method that happens to have the same name - ((LogThings)new Program()).WriteLog()
calls LogThings.WriteLog()
, as that's the last implementation in the chain. The new
essentially "forces in" another vtable, resulting in this somewhat split-brained setup.
Please note that this description of a vtable is drastically oversimplified; there's plenty of good material out there on that topic however.
When monkey patching an instance method, can you call the overridden method from the new implementation?
EDIT: It has been 9 years since I originally wrote this answer, and it deserves some cosmetic surgery to keep it current.
You can see the last version before the edit here.
You can’t call the overwritten method by name or keyword. That’s one of the many reasons why monkey patching should be avoided and inheritance be preferred instead, since obviously you can call the overridden method.
Avoiding Monkey Patching
Inheritance
So, if at all possible, you should prefer something like this:
class Foo
def bar
'Hello'
end
end
class ExtendedFoo < Foo
def bar
super + ' World'
end
end
ExtendedFoo.new.bar # => 'Hello World'
This works, if you control creation of the Foo
objects. Just change every place which creates a Foo
to instead create an ExtendedFoo
. This works even better if you use the Dependency Injection Design Pattern, the Factory Method Design Pattern, the Abstract Factory Design Pattern or something along those lines, because in that case, there is only place you need to change.
Delegation
If you do not control creation of the Foo
objects, for example because they are created by a framework that is outside of your control (like ruby-on-rails for example), then you could use the Wrapper Design Pattern:
require 'delegate'
class Foo
def bar
'Hello'
end
end
class WrappedFoo < DelegateClass(Foo)
def initialize(wrapped_foo)
super
end
def bar
super + ' World'
end
end
foo = Foo.new # this is not actually in your code, it comes from somewhere else
wrapped_foo = WrappedFoo.new(foo) # this is under your control
wrapped_foo.bar # => 'Hello World'
Basically, at the boundary of the system, where the Foo
object comes into your code, you wrap it into another object, and then use that object instead of the original one everywhere else in your code.
This uses the Object#DelegateClass
helper method from the delegate
library in the stdlib.
“Clean” Monkey Patching
Module#prepend
: Mixin Prepending
The two methods above require changing the system to avoid monkey patching. This section shows the preferred and least invasive method of monkey patching, should changing the system not be an option.
Module#prepend
was added to support more or less exactly this use case. Module#prepend
does the same thing as Module#include
, except it mixes in the mixin directly below the class:
class Foo
def bar
'Hello'
end
end
module FooExtensions
def bar
super + ' World'
end
end
class Foo
prepend FooExtensions
end
Foo.new.bar # => 'Hello World'
Note: I also wrote a little bit about Module#prepend
in this question: Ruby module prepend vs derivation
Mixin Inheritance (broken)
I have seen some people try (and ask about why it doesn’t work here on StackOverflow) something like this, i.e. include
ing a mixin instead of prepend
ing it:
class Foo
def bar
'Hello'
end
end
module FooExtensions
def bar
super + ' World'
end
end
class Foo
include FooExtensions
end
Unfortunately, that won’t work. It’s a good idea, because it uses inheritance, which means that you can use super
. However, Module#include
inserts the mixin above the class in the inheritance hierarchy, which means that FooExtensions#bar
will never be called (and if it were called, the super
would not actually refer to Foo#bar
but rather to Object#bar
which doesn’t exist), since Foo#bar
will always be found first.
Method Wrapping
The big question is: how can we hold on to the bar
method, without actually keeping around an actual method? The answer lies, as it does so often, in functional programming. We get a hold of the method as an actual object, and we use a closure (i.e. a block) to make sure that we and only we hold on to that object:
class Foo
def bar
'Hello'
end
end
class Foo
old_bar = instance_method(:bar)
define_method(:bar) do
old_bar.bind(self).() + ' World'
end
end
Foo.new.bar # => 'Hello World'
This is very clean: since old_bar
is just a local variable, it will go out of scope at the end of the class body, and it is impossible to access it from anywhere, even using reflection! And since Module#define_method
takes a block, and blocks close over their surrounding lexical environment (which is why we are using define_method
instead of def
here), it (and only it) will still have access to old_bar
, even after it has gone out of scope.
Short explanation:
old_bar = instance_method(:bar)
Here we are wrapping the bar
method into an UnboundMethod
method object and assigning it to the local variable old_bar
. This means, we now have a way to hold on to bar
even after it has been overwritten.
old_bar.bind(self)
This is a bit tricky. Basically, in Ruby (and in pretty much all single-dispatch based OO languages), a method is bound to a specific receiver object, called self
in Ruby. In other words: a method always knows what object it was called on, it knows what its self
is. But, we grabbed the method directly from a class, how does it know what its self
is?
Well, it doesn’t, which is why we need to bind
our UnboundMethod
to an object first, which will return a Method
object that we can then call. (UnboundMethod
s cannot be called, because they don’t know what to do without knowing their self
.)
And what do we bind
it to? We simply bind
it to ourselves, that way it will behave exactly like the original bar
would have!
Lastly, we need to call the Method
that is returned from bind
. In Ruby 1.9, there is some nifty new syntax for that (.()
), but if you are on 1.8, you can simply use the call
method; that’s what .()
gets translated to anyway.
Here are a couple of other questions, where some of those concepts are explained:
- How do I reference a function in Ruby?
- Is Ruby’s code block same as C♯’s lambda expression?
“Dirty” Monkey Patching
alias_method
chain
The problem we are having with our monkey patching is that when we overwrite the method, the method is gone, so we cannot call it anymore. So, let’s just make a backup copy!
class Foo
def bar
'Hello'
end
end
class Foo
alias_method :old_bar, :bar
def bar
old_bar + ' World'
end
end
Foo.new.bar # => 'Hello World'
Foo.new.old_bar # => 'Hello'
The problem with this is that we have now polluted the namespace with a superfluous old_bar
method. This method will show up in our documentation, it will show up in code completion in our IDEs, it will show up during reflection. Also, it still can be called, but presumably we monkey patched it, because we didn’t like its behavior in the first place, so we might not want other people to call it.
Despite the fact that this has some undesirable properties, it has unfortunately become popularized through AciveSupport’s Module#alias_method_chain
.
An aside: Refinements
In case you only need the different behavior in a few specific places and not throughout the whole system, you can use Refinements to restrict the monkey patch to a specific scope. I am going to demonstrate it here using the Module#prepend
example from above:
class Foo
def bar
'Hello'
end
end
module ExtendedFoo
module FooExtensions
def bar
super + ' World'
end
end
refine Foo do
prepend FooExtensions
end
end
Foo.new.bar # => 'Hello'
# We haven’t activated our Refinement yet!
using ExtendedFoo
# Activate our Refinement
Foo.new.bar # => 'Hello World'
# There it is!
You can see a more sophisticated example of using Refinements in this question: How to enable monkey patch for specific method?
Abandoned ideas
Before the Ruby community settled on Module#prepend
, there were multiple different ideas floating around that you may occasionally see referenced in older discussions. All of these are subsumed by Module#prepend
.
Method Combinators
One idea was the idea of method combinators from CLOS. This is basically a very lightweight version of a subset of Aspect-Oriented Programming.
Using syntax like
class Foo
def bar:before
# will always run before bar, when bar is called
end
def bar:after
# will always run after bar, when bar is called
# may or may not be able to access and/or change bar’s return value
end
end
you would be able to “hook into” the execution of the bar
method.
It is however not quite clear if and how you get access to bar
’s return value within bar:after
. Maybe we could (ab)use the super
keyword?
class Foo
def bar
'Hello'
end
end
class Foo
def bar:after
super + ' World'
end
end
Replacement
The before combinator is equivalent to prepend
ing a mixin with an overriding method that calls super
at the very end of the method. Likewise, the after combinator is equivalent to prepend
ing a mixin with an overriding method that calls super
at the very beginning of the method.
You can also do stuff before and after calling super
, you can call super
multiple times, and both retrieve and manipulate super
’s return value, making prepend
more powerful than method combinators.
class Foo
def bar:before
# will always run before bar, when bar is called
end
end
# is the same as
module BarBefore
def bar
# will always run before bar, when bar is called
super
end
end
class Foo
prepend BarBefore
end
and
class Foo
def bar:after
# will always run after bar, when bar is called
# may or may not be able to access and/or change bar’s return value
end
end
# is the same as
class BarAfter
def bar
original_return_value = super
# will always run after bar, when bar is called
# has access to and can change bar’s return value
end
end
class Foo
prepend BarAfter
end
old
keyword
This idea adds a new keyword similar to super
, which allows you to call the overwritten method the same way super
lets you call the overridden method:
class Foo
def bar
'Hello'
end
end
class Foo
def bar
old + ' World'
end
end
Foo.new.bar # => 'Hello World'
The main problem with this is that it is backwards incompatible: if you have method called old
, you will no longer be able to call it!
Replacement
super
in an overriding method in a prepend
ed mixin is essentially the same as old
in this proposal.
redef
keyword
Similar to above, but instead of adding a new keyword for calling the overwritten method and leaving def
alone, we add a new keyword for redefining methods. This is backwards compatible, since the syntax currently is illegal anyway:
class Foo
def bar
'Hello'
end
end
class Foo
redef bar
old + ' World'
end
end
Foo.new.bar # => 'Hello World'
Instead of adding two new keywords, we could also redefine the meaning of super
inside redef
:
class Foo
def bar
'Hello'
end
end
class Foo
redef bar
super + ' World'
end
end
Foo.new.bar # => 'Hello World'
Replacement
redef
ining a method is equivalent to overriding the method in a prepend
ed mixin. super
in the overriding method behaves like super
or old
in this proposal.
C# Override virtual function without having to implement another class
if you have control over MyClass
, you can let the desired method call a delegate which can be replaced for every single object at runtime...
class MyClass
{
public void Func<SomeParameterType,SomeReturnType> myDelegate {get;set;}
public SomeReturnType myFunction(SomeParameterType parameter)
{
if(myDelegate==null)
throw new Exception();
return myDelegate(parameter);
}
}
...
MyClass obj = new MyClass();
SomeParameterType p = new SomeParameterType();
obj.myDelegate = (x)=>new SomeReturnType(x);
SomeReturnType result = obj.myFunction(p);
Related Topics
Single Occurrence Event with Ice_Cube Gem Using Start_Time and End_Time
Ruby on Rails Webpacker Can't Find Images Under Asset_Pack_Path
Why Does Date Exist in Ruby Before It Is Required
"Gem Update --System Is Disabled on Debian" Error
Convert 12 Hr Time to 24 Hr Format in Ruby
Ruby: How to Find Out If a Character Is a Letter or a Digit
Whenever Gem: I Set :Output But the Logfile Doesn't Show Up Where I'D Expect It To
Testing Hash Contents Using Rspec
How to Tell If I'm Running from Jruby VS. Ruby
Trouble Downgrading Ruby on Os X Mavericks
Collecting Hashes into Openstruct Creates "Table" Entry
Datetime with Mongodb/Mongoid and Rails 3 Not Populating
Alias_Method and Class_Methods Don't Mix
Ruby - Remove Pattern from String
Connecting to Web Services Using Rails (Http Requests)
Sequel Accessing Many_To_Many Join Table When Adding Association