Howto alias a function like we did in Ruby? (monkey patching)

SilverDash

Veteran
Veteran
Joined
Oct 11, 2015
Messages
427
Reaction score
175
First Language
Dutch
Primarily Uses
RMMV
I'd like to call another method at the end of an existing function. For compatibility reasons I'd like to alias it instead.

I googled a bit around but couldn't find anything that I understand. It seems to be possible though.

I know I can say something like:

var x = Foo.SomeMethod;But what then.
 
Last edited by a moderator:

Iavra

Veteran
Veteran
Joined
Apr 9, 2015
Messages
1,797
Reaction score
868
First Language
German
Primarily Uses
var _alias_SomeMethod = Foo.SomeMethod;Foo.SomeMethod = function() { // do stuff _alias_SomeMethod.apply(this, arguments); // do stuff};"arguments" is a special, array-like variable available inside functions that contains all passed in parameters./edit: Make sure you put your plugin inside a self-executing function, like this:

Code:
(function() {    // your code})();
Otherwise, _alias_SomeMethod would be a public variable, which could be a huge compatibility issue.
 
Last edited by a moderator:

Mellye

Veteran
Veteran
Joined
Oct 24, 2015
Messages
347
Reaction score
279
First Language
Portuguese
You can also use call instead of apply. For example:

var this_is_an_alias = Game_Battler.prototype.onBattleStart;Game_Battler.prototype.onBattleStart = function() {    //Whatever you want to do before calling the aliased function    this_is_an_alias.call(this);   //Whatever you want to do after calling the aliased function}https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call
 
Last edited by a moderator:

Iavra

Veteran
Veteran
Joined
Apr 9, 2015
Messages
1,797
Reaction score
868
First Language
German
Primarily Uses
Yeah, i would use call() if you want to pass specific parameters. apply() is better suited to just pass everything along.
 

Mouser

Veteran
Veteran
Joined
Aug 19, 2012
Messages
1,245
Reaction score
266
First Language
English
Primarily Uses
"Aliasing" is a concept that doesn't exist in most languages. Note - you can break compatibility by aliasing as well as maintain it. It's not a 'magic bullet'.

Personally, I never used it, because I felt the risk of having the original method called when it shouldn't be was too great. Write tight, resilient code where the functions do what you want and you may find you don't need them. If you do, just rewrite the old functions and have them called by your new ones, this way you're sure that it's still your code handling everything.

At least, that's my view on the matter. Plenty of sound methodologies to go around, though :)
 

SilverDash

Veteran
Veteran
Joined
Oct 11, 2015
Messages
427
Reaction score
175
First Language
Dutch
Primarily Uses
RMMV
Thanks for the awesome replies. I however have one more problem. After editing the script the game requires me to delete and add the script manually again via the plugin managerfor the script to update. The game is not running while editing. How to fix that?
 

Iavra

Veteran
Veteran
Joined
Apr 9, 2015
Messages
1,797
Reaction score
868
First Language
German
Primarily Uses
"Aliasing" is a concept that doesn't exist in most languages. Note - you can break compatibility by aliasing as well as maintain it. It's not a 'magic bullet'.


Personally, I never used it, because I felt the risk of having the original method called when it shouldn't be was too great. Write tight, resilient code where the functions do what you want and you may find you don't need them. If you do, just rewrite the old functions and have them called by your new ones, this way you're sure that it's still your code handling everything.


At least, that's my view on the matter. Plenty of sound methodologies to go around, though :)
This way your plugin would only work if placed at the very top of the plugin list, because you overwrite every change done to those functions by other plugins. Take 2 or more of your plugins that work with the same classes and they won't be compatible at all.
Renaming a function isn't always a solution, because if you overwrite/extend a function that's been called by other classes, it needs to have the same name or it won't be called at all.

Thanks for the awesome replies. I however have one more problem. After editing the script the game requires me to delete and add the script manually again via the plugin managerfor the script to update. The game is not running while editing. How to fix that?
Usually, everything except for @plugindesc und @param should be reloaded every time the game starts. Is your game running on a webserver and your plugins get cached?
 
Last edited by a moderator:

SilverDash

Veteran
Veteran
Joined
Oct 11, 2015
Messages
427
Reaction score
175
First Language
Dutch
Primarily Uses
RMMV
No it's running just on my PC via steam. I tested it again but the script does not update until I manually remove the script from the plugin manager and add it again. I can't be the only one with that bug so I must be doing something wrong.

Oh and yes I do save the script before running the game again of course.

I better make a new topic for this.
 
Last edited by a moderator:

Mouser

Veteran
Veteran
Joined
Aug 19, 2012
Messages
1,245
Reaction score
266
First Language
English
Primarily Uses
This way your plugin would only work if placed at the very top of the plugin list, because you overwrite every change done to those functions by other plugins. Take 2 or more of your plugins that work with the same classes and they won't be compatible at all.

Renaming a function isn't always a solution, because if you overwrite/extend a function that's been called by other classes, it needs to have the same name or it won't be called at all.
Yes, but if more than one script is overwriting/extending the same function the odds for compatibility issues are pretty good already. You've got to go through them all and make sure they aren't overwriting each other or trying to do conceptually different things.

The point to 'renaming' in my example is that this way you're sure every script (and the base engine) calls your functions (which have the 'original' names). Then your code can decide whether or not the 'original' or any other versions of the functions need to be called. One handler for clean control flow.

It depends on what you're writing your scripts for: I write for my own project, so I really don't give two hoots about compatibility with other people's code (this is the path I think most people should take). If I use other people's plugins, then I go through and make sure their code is compatible with mine, and rewrite those plugins where necessary. Every developer needs to go through this process at some level regardless whenever you use different scripts.

If you're writing 'generic' scripts for other people to use, then you have a host of issues to worry about. This is not the place 'beginning' scripters should start at. Getting their own code working well with itself is challenge enough.

It still will always fall to the end user (project developer) to ensure compatibility though, for conceptual as well as technical reasons. A lot of people seem to think you should be able to drop all the scripts you want in a pile and have them all swim happily together in the pool, even if several of these scripts are trying to accomplish conflicting goals...
 
Last edited by a moderator:

Iavra

Veteran
Veteran
Joined
Apr 9, 2015
Messages
1,797
Reaction score
868
First Language
German
Primarily Uses
This kind of depends what you're trying to achieve. If you have a script like my popup plugin, which works mainly with its own classes and functions and only needs 1 or 2 aliased base methods to register itself with the engine, you can as well try to not break the engine for other plugins.


Now, if you have a menu overhaul or a complete battle system, chances are good that you won't be compatible to a lot of stuff from the get-go.
 

DarknessFalls

Rpg Maker Jesus - JS Dev.
Veteran
Joined
Jun 7, 2013
Messages
1,393
Reaction score
210
First Language
English
// Two ways:


var oldSomethingPrototypeFunctionNameMethod = Something.prototype.functionName;


Something.prototype.functionName = function(){


oldSomethingPrototypeFunctionNameMethod.call(this);


// your jazz here


}


// ES6, the way I do it:


AnotherClass extends Something {


functionName(){


super.functionName(this);


}


}
 

Iavra

Veteran
Veteran
Joined
Apr 9, 2015
Messages
1,797
Reaction score
868
First Language
German
Primarily Uses
Does ES6 actually makes sense, though? It's only syntactic sugar, anyway, and you'll need to compile back to ES5, which will make your code harder to read. I'd say it's better to make yourself familiar with the way it's done in ES5, so you also have an easier time understanding other people's plugins.
 

DarknessFalls

Rpg Maker Jesus - JS Dev.
Veteran
Joined
Jun 7, 2013
Messages
1,393
Reaction score
210
First Language
English
Does ES6 actually makes sense, though? It's only syntactic sugar, anyway, and you'll need to compile back to ES5, which will make your code harder to read. I'd say it's better to make yourself familiar with the way it's done in ES5, so you also have an easier time understanding other people's plugins.
I know how its done in both ways and all es6 is, is a thin wrapper around es5's prototypes
 

SilverDash

Veteran
Veteran
Joined
Oct 11, 2015
Messages
427
Reaction score
175
First Language
Dutch
Primarily Uses
RMMV
<removed>. I did something stupid nevermind.
 
Last edited by a moderator:

kentaromiura

Veteran
Veteran
Joined
Nov 1, 2015
Messages
46
Reaction score
26
First Language
English
Primarily Uses
let's say you have this function:

function foo(){ console.log('foo', arguments);}you can monkey patch it by doing:
 

function foo(){ console.log('foo', arguments);}foo = function(foo){ // notice that foo here can be named as you like return function(){ // this function is the monkey patched one console.log('before foo'); // by passing `this` we ensure it will work even for methods foo.apply(this, arguments); console.log('after foo'); };}(foo); // you're passing here a reference to the original foo// call itfoo(1, 2, 3);Notice that leaking arguments is not a good idea as it kills performance optimizations (at least in V8, https://github.com/petkaantonov/bluebird/wiki/Optimization-killers), so it's better to create a copy of it,

the usual solution before ES 2015 was to use `Array.prototype.slice` (in ES 2015 you will use rest and spread and forgot about arguments):

function foo(){ console.log('foo', arguments);}foo = function(foo){ return function(){ console.log('before foo'); foo.apply(this, Array.prototype.slice(arguments)); console.log('after foo'); };}(foo);// call itfoo(1, 2, 3);Of course, this is for answering to your original question,

now if this is a good idea or not depends of why you ask the question,

generically speaking it may not be a good idea,

it's better to create a new function and use the original there,

but if this for other reasons (eg debugging some code) it may be ok.
 

DarknessFalls

Rpg Maker Jesus - JS Dev.
Veteran
Joined
Jun 7, 2013
Messages
1,393
Reaction score
210
First Language
English
Monkey patching should not be done, it causes more problems he aliasing ... 
 

Tsukihime

Veteran
Veteran
Joined
Jun 30, 2012
Messages
8,564
Reaction score
3,876
First Language
English
What's the difference between monkey patching and aliasing?


I always thought aliasing was just the solution people used to monkey patch things?
 

SilverDash

Veteran
Veteran
Joined
Oct 11, 2015
Messages
427
Reaction score
175
First Language
Dutch
Primarily Uses
RMMV
http://stackoverflow.com/questions/5626193/what-is-a-monkey-patch

http://stackoverflow.com/questions/394144/what-does-monkey-patching-exactly-mean-in-ruby

Monkey patching is when you replace methods of a class at runtime (not adding new methods).
An alias should be a monkeypatch as well. At least it's for me :p .

So I'm not sure if this topic in Javascript would count as monkeypatching. It's not done at runtime I think. But I meant the Ruby equivalent of aliasing in Javascript.
 
Last edited by a moderator:

DarknessFalls

Rpg Maker Jesus - JS Dev.
Veteran
Joined
Jun 7, 2013
Messages
1,393
Reaction score
210
First Language
English
I wish the api was different such that we didnt have to do either, I find that a lot of times people have been forgetting to call the parent ... 
 

Tsukihime

Veteran
Veteran
Joined
Jun 30, 2012
Messages
8,564
Reaction score
3,876
First Language
English
I wish the api was different such that we didnt have to do either, I find that a lot of times people have been forgetting to call the parent ...
Are you referring to MV codebase, or javascript?


In ruby we had to call super explicitly if we wanted to invoke the superclass' method.


I don't know of any language that automatically calls parent method.
 
Last edited by a moderator:

Latest Threads

Latest Posts

Latest Profile Posts

Hike was successful guys! I made it to the top!
Add Film-like Visual Effects During Test-Play, Deploy Games with Electron | RPG Maker News #69

brain broken as soon as i figure out whats wrong with my game im taking a long nap
Hey guys anyone is interested in playing my game? Just PM me and I'll give you a Steam key! Here's my latest video! ->
cst.PNG
What would you assume this thing was/is?

Forum statistics

Threads
112,182
Messages
1,066,418
Members
145,776
Latest member
RodAlvenis
Top