class Parent
class << self
def real_method() "Parent" end
alias :fake_method :real_method
end
end
class Child < Parent
def real_method() "Child" end
end
But it doesn't:
Child.fake_method # ==> returns "Parent" instead of "Child"
If I replace the alias with a real method definition, e.g.
def fake_method() real_method end
then it works the way I expect (Child.fake_method returns "Child").
So what is it about "alias" that bypasses the override? Do I have to
replace my aliases with extra wrapper methods to get the behavior I'm
looking for?
As far as I can tell (or explain), alias and alias_method work by
creating a new copy of the method. One way to think about it is if you
had the block stored in a variable because you created the first
method like so
class Blah
meth = Proc.new { puts 'hi' }
define_method :first, &meth
end
Then aliasing the method like `alias :copy :first` is the same as
`define_method :copy, &meth`.
I ran into problems with the same sort of behavior when I was trying
to test-drive an addition of a simple alias for a complicated method,
and I assumed that I could simply test that calling the alias called
the original method with the same arguments. Nope! Calling the alias
went through the same complicated steps as the original. So I changed
the alias_method line to a wrapper function and went on my merry way.
···
On Aug 14, 9:35 am, Marcos <markjr...@gmail.com> wrote:
So what is it about "alias" that bypasses the override? Do I have to
replace my aliases with extra wrapper methods to get the behavior I'm
looking for?
I do not see anything surprising here, you aliased a method in parent
and not in child. When calling child's fake method there is none and
the lookup finds the parent's method.
When however you wrap the parent's methods after having found parent's #fake it calls
real which is found in the child. Note that parent's #real is never
called in none of the two cases!
HTH
Robert
···
On Fri, Aug 14, 2009 at 4:35 PM, Marcos<markjreed@gmail.com> wrote:
This seems like it should work:
class Parent
class << self
def real_method() "Parent" end
alias :fake_method :real_method
end
end
class Child < Parent
def real_method() "Child" end
end
But it doesn't:
Child\.fake\_method \# ==> returns "Parent" instead of "Child"
If I replace the alias with a real method definition, e.g.
def fake\_method\(\) real\_method end
then it works the way I expect (Child.fake_method returns "Child").
So what is it about "alias" that bypasses the override? Do I have to
replace my aliases with extra wrapper methods to get the behavior I'm
looking for?
class Parent
class << self
def real_method() "Parent" end
alias :fake_method :real_method
You don't have to use symbols there; you can do:
alias fake_method real_method
because alias is a keyword, not a method, so it can take "raw"
identifiers.
end
end
class Child < Parent
def real_method() "Child" end
You mean def self.real_method, I think.
end
But it doesn't:
Child.fake_method # ==> returns "Parent" instead of "Child"
If I replace the alias with a real method definition, e.g.
def fake_method() real_method end
then it works the way I expect (Child.fake_method returns "Child").
So what is it about "alias" that bypasses the override? Do I have to
replace my aliases with extra wrapper methods to get the behavior I'm
looking for?
The aliasing just means that there's now a method called
Parent.fake_method. It doesn't add any methods to any class other than
the class where it's executed (in this case, the singleton class of
Parent). Basically, creating an alias has the same footprint as
writing a method definition.
David
···
On Fri, 14 Aug 2009, Marcos wrote:
--
David A. Black / Ruby Power and Light, LLC / http://www.rubypal.com
Q: What's the best way to get a really solid knowledge of Ruby?
A: Come to our Ruby training in Edison, New Jersey, September 14-17!
Instructors: David A. Black and Erik Kastner
More info and registration: http://rubyurl.com/vmzN
Small correction - that should be "def self.real_method". All class
methods, not instance methods...
···
On Aug 14, 10:31 am, Marcos <markjr...@gmail.com> wrote:
This seems like it should work:
class Parent
class << self
def real\_method\(\) "Parent" end
alias :fake\_method :real\_method
end
end
class Child < Parent
def real\_method\(\) "Child" end
end
I find it mildly annoying that 'alias' doesn't actually alias the
method (i.e. multiple names for the same thing). Instead, alias
just replicates an existing method body and associates a new
name with the replica. Seems like 'replicate' would be a better
keyword for the current semantics.
I also have the inability to ever remember which argument to alias
is the new name and which argument is the old name.
Did 'alias' work differently in the early days of Ruby such that
the semantics changed but not the keyword?
···
On Aug 14, 2009, at 2:25 PM, David A. Black wrote:
The aliasing just means that there's now a method called
Parent.fake_method. It doesn't add any methods to any class other than
the class where it's executed (in this case, the singleton class of
Parent). Basically, creating an alias has the same footprint as
writing a method definition.
I believe your alias version is equivalent to this:
···
==========
class Parent
Parent.real_method
"Parent"
end
Parent.fake_method #alias creates a copy of real_method
"Parent"
end
end
and your wrapped version is this:
=========
class Parent
def Parent.real_method
"Parent"
end
def Parent.fake_method
real_method #<-----**BIG DIFFERENCE**
end
end
Those Parent classes are clearly not the same. If you add the following
code to your wrapped version:
=========
class Child < Parent
def self.real_method
"Child"
end
end
puts Child.fake_method
--output:--
Child
the message "fake_method" is sent to the Child object (=a class object).
The Child object has no method named "fake_method" defined on it, e.g.
def Child.fake_message, so lookup proceeds to the superclass class
object, i.e. Parent. The Parent object does have the method
"fake_method" defined on it, so Parent.fake_method is executed.
Parent.fake_method really looks like this:
def Parent.fake_method
self.real_method
end
In this case, self is the Child object--because when you write:
puts Child.fake_method
the fake_method message gets sent to the Child object--in other words
Child is calling fake_method, and the caller is self inside a method.
Therefore, calling self.real_method (inside fake_method) is equivalent
to calling Child.real_method. And calling Child.real_method sends the
message real_method to the Child object. As a consequence, a new lookup
begins starting with the Child object. Because Child has a method
called real_method defined on it, Child.real_method executes.
It's highly probable that the above description contains some factual
errors, but the esteemed members who previously posted above will surely
correct them below.
I find it mildly annoying that 'alias' doesn't actually alias the
method (i.e. multiple names for the same thing). Instead, alias
just replicates an existing method body and associates a new
name with the replica. Seems like 'replicate' would be a better
keyword for the current semantics.
I also have the inability to ever remember which argument to alias
is the new name and which argument is the old name.
Did 'alias' work differently in the early days of Ruby such that
the semantics changed but not the keyword?
+1 to all of above, albeit mildly for me too.
In practice I usually end up with
def myalias(*a,&b); orig(*a,&b); end
even if it started out as an "alias". I don't mind not having a language construct for this purpose, since the above is so compact and clear.
···
--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
In message "Re: Class method aliased in superclass bypasses subclass overrides" on Sat, 15 Aug 2009 04:31:35 +0900, Gary Wright <gwtmp01@mac.com> writes:
Did 'alias' work differently in the early days of Ruby such that
the semantics changed but not the keyword?
FYI, alias worked as it is from the very early days of Ruby.
Where the same body (rather than two identical copies) is used for
both methods; the traditional CS kind of "alias". In UNIX terms, it's
an ln, not a cp.
To stretch the analogy a bit, what I was expecting was more like "ln -
s". But clearly that's not correct, so I'll just stick with the
wrapper methods.
Thanks for all the replies.
···
On Aug 15, 8:31 am, 7stud -- <bbxx789_0...@yahoo.com> wrote:
I believe your alias version is equivalent to this:
==========
class Parent
Parent.real_method
"Parent"
end
Parent.fake_method #alias creates a copy of real_method
"Parent"
end
It is strange that as a Unix guy I have never been bothered by this.
As an important use case for my aliases (although I prefer the
alias_method method) I am often using this pattern:
alias_method :__behavior__, :behavior
remove_method :behavior # for 1.9
define_method :behavior do ...
...
__behavior__
...
thus the current behavior became second nature.
Maybe it would be nice to have a synonym method in Module that does
what you two expected from alias, that is being dynamically redefined
with its target.
Cheers
Robert
···
On Fri, Aug 14, 2009 at 10:46 PM, Joel VanderWerf<vjoel@path.berkeley.edu> wrote:
Gary Wright wrote:
I find it mildly annoying that 'alias' doesn't actually alias the
method (i.e. multiple names for the same thing). Instead, alias
just replicates an existing method body and associates a new
name with the replica. Seems like 'replicate' would be a better
keyword for the current semantics.
I also have the inability to ever remember which argument to alias
is the new name and which argument is the old name.
Did 'alias' work differently in the early days of Ruby such that
the semantics changed but not the keyword?
+1 to all of above, albeit mildly for me too.
In practice I usually end up with
def myalias(*a,&b); orig(*a,&b); end
even if it started out as an "alias". I don't mind not having a language
construct for this purpose, since the above is so compact and clear.
--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407