Incorrectly using alias as super

Tsukihime

Veteran
Veteran
Joined
Jun 30, 2012
Messages
8,564
Reaction score
3,846
First Language
English
Can you explain how overwriting the method and then aliasing it would be a better solution than simply overwriting it and adding your logic?
 

Engr. Adiktuzmiko

Chemical Engineer, Game Developer, Using BlinkBoy'
Veteran
Joined
May 15, 2012
Messages
14,682
Reaction score
3,003
First Language
Tagalog
Primarily Uses
RMVXA
As I said, that is to ensure that even if you have multiple scripts that will add a logic to that same child method, it would still work. If you're sure that only one script would overwrite that method, then by all means, just overwrite it.


IMHO, it's still better to account for the possibility of making another script that would alter that same method, hence my 2nd proposal.


PS: You might need to delete the def from the succeeding scripts though so that only one script has it. :)
 
Last edited by a moderator:

Tsukihime

Veteran
Veteran
Joined
Jun 30, 2012
Messages
8,564
Reaction score
3,846
First Language
English
Maybe it is just a typo on your part, but

class Game_Actor def on_battle_end super #<------- this end alias on_battle_end_one on_battle_end def on_battle_end on_battle_end_one #add your logic here endend
basically overwrites everything that may have been defined beforehand (such as other scripts that aliased the same method)I'm not sure if there is even a solution to this problem, short of forcing every method in the default scripts to call super (if they do not already do so) because any method is fair game for aliasing, and making sure if you do any inheritance of your own, make sure there are super calls.

I alias child class methods all the time even though they inherit from the parent, so every script where I do this is vulnerable to the bug.
 
Last edited by a moderator:

Engr. Adiktuzmiko

Chemical Engineer, Game Developer, Using BlinkBoy'
Veteran
Joined
May 15, 2012
Messages
14,682
Reaction score
3,003
First Language
Tagalog
Primarily Uses
RMVXA
Yeah which is why as I PS'd above:

PS: You might need to delete the def from the succeeding scripts though so that only one script has it. :)
 

Another Fen

Veteran
Veteran
Joined
Jan 23, 2013
Messages
564
Reaction score
275
First Language
German
Primarily Uses
As far as I can see, that would be exactly what the unless instance_methods(false).include?(...) I added to your solution would be for. Despite you'd have to write up to 6 lines for a single alias...
 
Last edited by a moderator:

IMP1

"haystack".scan(/needle/)
Veteran
Joined
Mar 6, 2014
Messages
61
Reaction score
44
First Language
English
Primarily Uses
RMVXA
The main problem of this way is that it only works once. If you have two scripts that extend the method this way, one of them will inevitably get lost. Of course you can weigh the risk of this happening in praxis, with aliasing you keep out of harm's way - if it wasn't for the issue Tsukihime stated.

Something like this would be problematic:

class A  def test    p 'A'  endendclass B < A  def test    super # Prints 'A'    p 'B'  endendclass A  alias :th_old_test :test  def test    th_old_test    p 'A2'  endend class B  def test    super  # Extend test. Without knowing B already defines test, p 'B' is lost    p "B52"  endendb = B.newb.test # Calls B.test, which calls super, which is A.test (including its aliased version)
While this should work, it is quite messy:

class A  def test    p 'A'  endendclass B < A  unless instance_methods(false).include?:)test) define_method:)test) { super() } end alias_method:)test_Bmod1, :test)  def test    test_Bmod1    p 'B'  endendclass A  alias :th_old_test :test  def test    th_old_test    p 'A2'  endend class B  unless instance_methods(false).include?:)test) define_method:)test) { super() } end alias_method:)test_Bmod2, :test)  def test    test_Bmod2    p "B52"  endendb = B.newb.test # Calls B.test, which calls super, which is A.test (including its aliased version
You... what?

This works fine:

class A    def foo        puts "A"    endendclass B < A    def foo        super        puts "B"    endendclass A    alias :old_a_foo :foo unless $@    def foo        old_a_foo        puts "A2"    endendclass B    alias :old_b_foo :foo unless $@    def foo        old_b_foo        puts "B2"    endendb = B.newb.foo # This prints, A, A2, B, B2Super is for calling superclass's method. Alias is for adding content to the method. They're for different things. You don't need all this define_method hackery.

EDIT: I see... the issue is two different scripts created a subclass's method. Well, maybe you should just alias the method in the subclass and have your script underneath any others that might alias the superclass's method.

If someone has two scripts that are providing (different) functionality to a subclass's previously "undefined" (obviously defined in superclass) method, then there will probably be other issues, and maybe there should be some compatability problems. "Fixing" things like the way people have suggested (when really you probably don't need to yet) are just gonna cause more problems down the line that will be harder to locate.

I mean, you could always just alias the superclass, and add a .is_a?(Subclass) if you wanted to, that way you don't have to deal with overwriting the subclass at all, but this also just defeats the purpose of class inheritance.
 
Last edited by a moderator:

TheoAllen

Self-proclaimed jack of all trades
Veteran
Joined
Mar 16, 2012
Messages
5,592
Reaction score
6,522
First Language
Indonesian
Primarily Uses
RMVXA
Separate the script into two parts for best case

One called Basic Module / Service pack that should be placed all above custom scripts (include other's basic modules as well). 

As for example

class Game_Actor  def on_battle_end    super  endendAnd the another one is your actual code.

The Basic Module / Service pack is not really required. But it's recommended

Well, maybe some of the script users usually ignore the 'unimportant' part which they don't really know what is that means I guess. But that is their risks.
 
Last edited by a moderator:

Galenmereth

Retired
Veteran
Joined
May 15, 2013
Messages
2,248
Reaction score
2,158
First Language
English
Primarily Uses
N/A
I may be misunderstanding you here, but I think what you're looking for is alias_method in this problem scenario, instead of alias. Here's a good explanation: http://wikimatze.de/method-alias-in-ruby/

The part of most interest is the difference between alias and alias_method:

Alias will look at the value of self lexically where the aliased keyword lies. Alias_method use the value of self during runtime which may be a subclass where the call is lexically located.
 
Last edited by a moderator:

TheoAllen

Self-proclaimed jack of all trades
Veteran
Joined
Mar 16, 2012
Messages
5,592
Reaction score
6,522
First Language
Indonesian
Primarily Uses
RMVXA
Tried to change tsukihime's scenario with alias_method and it didn't solve the problem

I had read another article about alias and alias_method here

http://blog.bigbinary.com/2012/01/08/alias-vs-alias-method.html

Basically it just allow to be called in runtime, perhaps?

Code:
def rename  alias_method :new_method, :testend class A  def test    puts 'A'  end  renameend
 
Last edited by a moderator:

Another Fen

Veteran
Veteran
Joined
Jan 23, 2013
Messages
564
Reaction score
275
First Language
German
Primarily Uses
alias and alias_method differ when it comes to something like this:

class A  def self.test_alias    alias test12 test1  # Alias will Copy the method defined by A  end  def test1    " TestA "  end  def self.test_alias_method    alias_method:)test22, :test2)  # AliasMethod will Copy the method defined by "self"  end  def test2    " TestA "  endendclass B < A  def test1    " TestB "  end  test_alias  def test2    " TestB "  end  test_alias_methodendp B.new.test12p B.new.test22p A.new.test12p A.new.test22# =># " TestA "# " TestB "# " TestA "# Undefined Method test22 for <A>
In the given case the use of alias or alias_method should not make any difference.

When a method is already defined within a superclass I don't think there would be more issues when extending it then there would be when extending a method defined within the same class using alias. After all, the idea behind it is still the same: 'do what you're already ought to do and add the stuff I want'. So I'd rather speak of an implicitely defined method here than an undefined one.
 
Last edited by a moderator:

Galenmereth

Retired
Veteran
Joined
May 15, 2013
Messages
2,248
Reaction score
2,158
First Language
English
Primarily Uses
N/A
Yeah seems like I missed the point entirely. It's what I get for replying to stuff like this before I've had my coffee... :D

On the topic at hand, I believe this is relevant and something I am going to implement in my scripts going forward, because it is much much easier to deal with when things get complicated (as they usually do): http://stackoverflow.com/a/4471202

It's not applicable in all instances, but if this is done my more scripters, it could make compatibility an easier task in many cases.
 
Last edited by a moderator:

Users Who Are Viewing This Thread (Users: 0, Guests: 1)

Latest Threads

Latest Posts

Latest Profile Posts

Couple hours of work. Might use in my game as a secret find or something. Not sure. Fancy though no? :D
Holy stink, where have I been? Well, I started my temporary job this week. So less time to spend on game design... :(
Cartoonier cloud cover that better fits the art style, as well as (slightly) improved blending/fading... fading clouds when there are larger patterns is still somewhat abrupt for some reason.
Do you Find Tilesetting or Looking for Tilesets/Plugins more fun? Personally I like making my tileset for my Game (Cretaceous Park TM) xD
How many parameters is 'too many'??

Forum statistics

Threads
105,860
Messages
1,017,038
Members
137,568
Latest member
invidious
Top