Grey Line

Just finished writing an article called “Polymorphism Without Interfaces”. I challenge you to review and explain the code below:

for(var i:uint = 0; i < workers.length; i++) {

var p:* = workers[i]["increasePay"];

output.text+=p==undefined?”no luck”:p(5);

}

The person who writes the best explanation, will get a free copy of my e-book “Java programming for kids, parents and grandparents “. I’m sure people understand the syntax of this code snippet, but I’m looking for an explanation of WHY it’s written this way.

Good luck,

Yakov

14 Comments »

  1. Mark Piller said,

    October 9, 2006 @ 9:41 am

    Although, “polymorphism without interfaces” sounds like a counter-oo concept, here’s an explanation of the code snippet:

    You iterate over some instances in the workers array and for each instance get the “increadePay” function reference. If the function is not available for a particular object instance, you append “no luck” to the output field, otherwise, you add whatever increasePay( 5 ) returns.

    Mark

  2. Keith Peters said,

    October 9, 2006 @ 10:01 am

    I understand it. You have an array of objects which may or may not have an “increasePay” method. You want to loop through it and if the object has that method call it and add the result to the text field. If not, add “no luck” to the text field.

    As for WHY it’s written the way it is… obfuscation?

  3. spender said,

    October 9, 2006 @ 10:46 am

    The code iterates through an array (workers).
    For each object in the array, you are testing to see if it has a property called increasePay
    If the object has a property increasePay, you treat it as if it were a function (although this is not checked), and invoke it, and append the result to the string output.text. If it does not have the property increasePay, then you add “no luck” to the string output.text instead.

    So, the intent of the code (although without checking p to see if it is a Function object, I’d venture that the code is incomplete), is to check if the objects in the array support the function increasePay. If so, you take further action.

    Wouldn’t it be better to have the objects implement an interface defining increasePay, (e.g. IPayRiseable)? That way you could check:

    if(worker[i] is IPayRiseable)
    {
    worker[i].increasePay(5);
    }

    I like your blog, btw.

    Cheers.

  4. spender said,

    October 9, 2006 @ 10:56 am

    I guess the reason you didn’t use an interface is because the title of your article is “Polymorphism Without Interfaces”. Doh!

    You still need to check that (p is Function) rather than if (p==undefined)… ideally you’d introspect to check that the signature of p is p(n:Number) as well. Pretty messy if you ask me!

    /spender

  5. Dirk said,

    October 9, 2006 @ 11:48 am

    Aside from the typo (should be workers[i] instead of worker[i] I think) here’s my try:

    the approach illustrates how to invoke common methods on objects that don’t have to share a common type. So instead of checking each worker object against a type (or interface), the construct tries to resolve increasePay on the current object. As this dynamic construct either evaluates to undefined or a Function reference, the shorthand if/else is then used to invoke p (in this example a Function reference) with an argument and return its return value or just uses a default String return value if the method increasePay cannot be resolved.

    Of course, if the object implements a ”increasePay” field which is not a Function object but e.g. a String, then this causes a runtime error.

  6. Kristof said,

    October 9, 2006 @ 11:56 am

    //you could also write it like this
    //I’ll leave the implementation of implementsMethod to you
    for(var i:uint = 0; i

  7. Yakov Fain said,

    October 9, 2006 @ 12:34 pm

    I’ve emailed my e-book to Dirk ans spender already for providing more detailed answers than others.

    I’ll be happy to give away more copies of the e-book to those of you who will provide detailed explanations of why some particular syntax constructs were used in this example. Just analyze each line of this code and provide your reasoning/alternatives.

  8. francis bourre said,

    October 12, 2006 @ 12:07 pm

    last but not least, polymorphism with interfaces allow precompilation error checking.
    Does this old-school obfuscated code snippet tries to highlight bad code practices ? :p

  9. erenbali said,

    October 24, 2006 @ 9:52 am

    here is my guess if i’m not that much late.

    there is a base class Worker of lets say all workers in a company. there are some other classes extending Worker like Secretary, Engineer, Manager.. Let’s say just Manager and Engineer classes implement increasePay function.

    In such a situation we would probably keep an array of workers in the company for some batch processing needs(f.e paySalary..)
    these loop increasesPay of the workers that can increasePay

  10. Barney Boisvert said,

    October 31, 2006 @ 1:50 am

    It’s written that way because reducing lines of code was more important than readability For each worker, increase their pay by 5, if possible, appending the result to the output. Otherwise append “no luck” to the output. How about this version:

    for(var i:uint = 0; i

  11. Barney Boisvert said,

    October 31, 2006 @ 1:52 am

    View source on my previous comment to get the rest of it. No HTML escaping provided automatically, it seems, so my < got interpreted literally. To test……

    alert(“uh, oh!”);

  12. Evert said,

    October 31, 2006 @ 3:37 am

    This is called duck-typing

  13. Tom Chiverton said,

    November 1, 2006 @ 5:59 am

    http://anjalixz.tripod.com/renderer3d/Example3da.html

  14. Tom Chiverton said,

    November 1, 2006 @ 6:00 am

    (pardon my last comment)
    Why wouldn’t I have hasIncreasePay():Bool and increasePay(int):void methods ?

RSS feed for comments on this post · TrackBack URI

Leave a Comment