Monday, March 29, 2010

processing.js public members public to everyone but itself

Ok, here's what I'm doing. I'm trying to implement the private/public keywords for processing.js

And here are the problems. First attempt was ages ago, and that was to, inside a class, use this.variable; for public, and var variable; for private. This sort of worked, as it allowed me to use public members freely inside and outside the object, and I could not access private members, until they were set from outside the object.

Considering this class:

class Obj {
private String item;
public void setItem(String str) {
item = str;
}
public String getItem() {
return item;
}
}

and consider this usage:

Obj thing = new Obj();
thing.setItem("this has been set");
println(thing.getItem()); // prints "this has been set"
println(thing.item); // prints undefined, as it's not been used yet

Everything working as intended, until I try this:

thing.item = "if you see this, it's broken";
println(thing.getItem()) // prints "if you see this, it's broken" :(

It's not very useful if private is restrictive but not protective. I thought the whole purpose was to protect you, the person using the object, from themselves, and not just restrict them from, themselves.

Anyway, I wasn't done there. I spent this weekend rewriting the way processing.js translates a class. I was changing it so when you created an object, instead of returning an object, I would call a function that would set all the private members and functions, then return an object literal that would contain all the public variables and functions, which had access to the members in the preceding function, but those members no longer existed, and it worked! Here is an example of what I mean:

function Obj() {
var privateVariable = "It's a secret to everybody";
function privateFunction() {
...
}
return {
publicVariable: "...",
publicFunction: function() { return privateVariable; }
};
}

Usage of this is like so:

var obj = new Obj();
alert(obj.publicVariable); // alertss "..."
alert(obj.publicFunction()); // alerts "It's a secret to everybody"

Everything as expected until I try this... Consider this modified class:

function Obj() {
return {
publicVariable: "...",
publicFunction: function() { return publicVariable; }
};
}

and this usage:

var obj = new Obj();
alert(obj.publicFunction()); // crashes

So now, a private member is private to everyone but itself, which is good, and a public member is public to everyone... but itself. Two solutions, with two completely opposite caveats.

Final though: while writing this, I was thinking, and organizing my thoughts (kinda the point of blogging, for me) and I have two options I need to explore.

  • Change the public functions to use public variables with a "this." before it. Example:

    return {
    publicVariable: "...",
    publicFunction: function() { return this.publicVariable; }
    };

    This works, but isn't very practical as I'm translating Java-like class syntax into the javascript you see now, and I don't want to go through all the code, just the structure; this method would require looking for the usage of all public variables, once I have a list of public variables, and add "this.". Not ideal.

  • Another option, which I'll try, is to add a list of public variables at the top of the code inside a function, like this:

    return {
    publicVariable: "...",
    publicFunction: function() { var publicVariable = this.publicVariable; return publicVariable; }
    };

    Passes the public variable inside this, into a new variable with said name, so I don't have to touch the code inside the function, just add a header of sorts. I would have to do this with functions too.

1 comment: