Function overloading

359 views
Skip to first unread message

Klaus Reimer

unread,
Sep 28, 2012, 6:12:54 AM9/28/12
to closure-comp...@googlegroups.com
Hello,

Is it possible to have some kind of function overloading with Closure
Compiler? Let's take this function as example:

/**
* @param {!Dimension|number} sizeOrWidth
* @param {number=} height
*/
function setSize(sizeOrWidth, height) {}

This function can be called in two ways (Actual decision how to
interpret the parameters is up to the implementation of course):

setSize(new Dimension(1024, 768));
setSize(1024, 768);

Unfortunately according to the type annotations it also allows illegal
use like this:

setSize(1024);
setSize(new Dimension(1024, 768), 512);

And it even gets worse when it comes to return types which depend on the
parameter types. Take a look at the jQuery externs and you can imagine
how many wrong API usages Closure Compiler can't detect.

It's clear that JavaScript doesn't support overloading but is it somehow
possible to give Closure Compiler more hints about how this function can
be used? If not, anyone here thinks this would be a cool feature? Maybe
it could be implemented like this:

/**
* @param {!Dimension} size
* @overload
*/
function setSize(size) {}

/**
* @param {number} width
* @param {number} height
* @overload
*/
function setSize(width, height) {}

/**
* Sets the element size.
*
* @param {!Dimension|number} sizeOrWidth
* @param {number=} height
* @overloaded
*/
function setSize(sizeOrWidth, height)
{
// Real implementation goes here.
}

So there are two dummy functions (Must be defined before the real one,
or in an externs file) annotated with "@overload" and the real function
annotated with "@overloaded". Compiler can check if the
@overload-functions have compatible signatures to the @overloaded
function. And function calls can be checked against all the @overload
functions (Must NOT check against the real @overloaded function!).
Documentation tools can ignore the @overloaded function and only list
the @overload functions.

--
Bye, K <http://www.ailis.de/~k/>
[A735 47EC D87B 1F15 C1E9 53D3 AA03 6173 A723 E391]

Jay Young

unread,
Sep 29, 2012, 1:03:37 AM9/29/12
to closure-comp...@googlegroups.com
I'm afraid I don't have a good answer, but your proposal where there are multiple implementations of the same function won't fly because code has to have the same behavior before and after compilation.  In your example, the last function would overwrite the previous two definitions.

John Lenz

unread,
Oct 1, 2012, 11:36:53 AM10/1/12
to closure-comp...@googlegroups.com
Ideally, you would be able to do something like this and have the compiler warn that it doesn't match any of the possible function signatures:

/** @type {(function(!Dimension):void)|function(number|number):void)} */
function setSize(x,y) {};

Being about to define this would make a lot of javascript libraries type check with higher fidelity (jQuery, etc).

Chad Killingsworth

unread,
Oct 1, 2012, 11:53:48 AM10/1/12
to closure-comp...@googlegroups.com
@John: What's preventing that from working in an assignment?

/** @type {(function(!Dimension):void)|function(number|number):void)} */
var a = function(x,y) {}

For jQuery, it's also the differing number of arguments that is an issue.

Chad

John Lenz

unread,
Oct 1, 2012, 11:57:13 AM10/1/12
to closure-comp...@googlegroups.com
On Mon, Oct 1, 2012 at 8:53 AM, Chad Killingsworth <chadkill...@missouristate.edu> wrote:
@John: What's preventing that from working in an assignment?

This works not but you get the same results as if you had merged it into a single signature (I haven't test this recently)
 
/** @type {(function(!Dimension):void)|function(number|number):void)} */
var a = function(x,y) {}

For jQuery, it's also the differing number of arguments that is an issue.

This example also has a differing number of arguments, can you be more explicit?

Chad Killingsworth

unread,
Oct 1, 2012, 12:25:13 PM10/1/12
to closure-comp...@googlegroups.com
On Monday, October 1, 2012 10:57:35 AM UTC-5, John wrote:

For jQuery, it's also the differing number of arguments that is an issue.

This example also has a differing number of arguments, can you be more explicit?

Nope. Just missed it.

Rhys Brett-Bowen

unread,
Oct 1, 2012, 8:02:05 PM10/1/12
to closure-comp...@googlegroups.com
in https://github.com/rhysbrettbowen/G-closure I just define extra parameters as optional and give the types as they may be at the start then do some sanity checking and fiddling at the start of each function to get the inputs as I need them.

Klaus Reimer

unread,
Oct 2, 2012, 2:12:50 AM10/2/12
to closure-comp...@googlegroups.com
That's exactly what should happen. The REAL implementation is only the
last function. The other two functions are just dummy functions which
are just there so Closure Compiler can parse the function definition
from it. These functions are empty. Just like methods in an interface
which are also functions which are just there for closure compiler and
which are never used by JavaScript itself.

Klaus Reimer

unread,
Oct 2, 2012, 2:16:42 AM10/2/12
to closure-comp...@googlegroups.com
On 10/01/2012 05:36 PM, John Lenz wrote:
> /** @type {(function(!Dimension):void)|function(number|number):void)} */
> function setSize(x,y) {};

Problem with this is that is isn't really compatible with JsDoc. So
there is no way to document the various function usages properly.

Klaus Reimer

unread,
Oct 2, 2012, 2:48:31 AM10/2/12
to closure-comp...@googlegroups.com
On 10/02/2012 08:12 AM, Klaus Reimer wrote:
> That's exactly what should happen. The REAL implementation is only the
> last function.

To give a runnable example please look here:

http://jsfiddle.net/StpxN/5/

This example defines a Vector class with an overloaded set() method. The
first set method takes a pair of numbers as parameters, the second one
takes an other vector as parameter.

This overloaded method is defined by using three functions:

The first two methods are just dummy functions (Like the dummy functions
in interfaces). The third method is the real implementation which has to
do the usual magic to determine how to process the various types of
parameters.

So there is no compilation magic here. JavaScript can work with it
because the real implementation overwrites the dummy implementation. A
JsDoc generator can work with it (after implementing support for the
@overload and @overloaded annotations to determine which methods to
document and which methods to ignore) because there are real
documentation bodies and @param and @return annotations for each method.
And Closure Compiler could validate the method usages according to the
interfaces of the @overload methods. It would be even possible to define
one of the overload methods as @private and Closure Compiler can check
access based on the parameters.
Reply all
Reply to author
Forward
0 new messages