View Full Version : An additional "private" constructor
IQAndreas
January 25th, 2010, 05:27 AM
I have a Color class where all the data is stored in a single uint named "_value".
However, the constructor for Color looks like this:
public function Color(r:uint = 0, g:uint = 0, b:uint = 0):void
{ _value = (makeChar(r) << 16 | makeChar(g) << 8 | makeChar(b)); }
If I want to create a clone() method, I have to first convert the "_value" variable to an RGB object, then, the constructor automatically converts the object back into a hexadecimal value. Blatent waste of efficiency!
However, I would rather have the constructor be user friendly and allow them to type in each color value instead of one hex value (they can use the Color.fromHex() if they really want to, but it does the same as the clone() method and converts back and forth)
Is there any way to instantiate a class without going through the one single constructor function? Any way to set up a private constructor in addition to the public one?
Most Visual Stuido languages allowed you to have multiple constructors, and the chosen constructor is determined by the passed in arguments. This was REALLY convenient, but sadly, AS3 only allows one constructor, right? :(
Any workarounds?
dr_tchock
January 25th, 2010, 06:24 AM
Can't you you just pass the argument into the constructor and then get it to do what you want from there? Seems obvious, I know - I've probably misunderstood the outcome you want.
IQAndreas
January 25th, 2010, 06:55 AM
Can't you you just pass the argument into the constructor and then get it to do what you want from there? Seems obvious, I know - I've probably misunderstood the outcome you want.
I don't quite understand you... I would like to have two different constructors, one private, and one public. I'm only using the Color class as an example. I have wanted to do this for several different classes several times.
//This constructor is for the people
//It's easier setting each color value individually
public function Color(r:uint = 0, g:uint = 0, b:uint = 0):void
{
//Converting from RGB to hex is slow and inefficient.
_value = RGBtoHEX(r, g, b);
}
private function Color(hex:uint):void
{
//Here I don't need any converting at all
_value = hex;
}
//Here, I want to clone the Color instance
public function clone():Color
{
//This is a REALLY bad idea.
//Here, I convert the hex value to RGB, and then the value is then
//converted back from RGB to hex!
var rgb:Object = HEXtoRGB(_value);
return new Color(rgb.r, rgb.g, rgb.b);
//GOOD IDEA
//I would prefer having a private constructor, so I don't need to convert back and forth
return new Color(_value);
}Do you understand?
Or do you mean using the "... args" parameter?
Yes, that is possible, however, then there is no type checking for the parameters, and then all errors have to be runtime errors.
I find that really handy when I want an array of items, but not when I want specific items in the constructor.
[MuG]
January 25th, 2010, 09:20 AM
I know its only an example but why don't you store the r, g & b parameters in the class so that when you clone the class you need only pass in those values again instead of converting back and then to again!?
In answer to your proper question: Can you have multiple constructors: No!
In addition you may not have any thing other then a public constructor.
Here is the livedocs link : http://livedocs.adobe.com/flex/2/docs/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00001842.html
Sorry!
IQAndreas
January 25th, 2010, 09:33 AM
;2531974']I know its only an example but why don't you store the r, g & b parameters in the class so that when you clone the class you need only pass in those values again instead of converting back and then to again!?
I have been thinking about that quite a bit, but that means the class takes up at least three times the amount of data than it needs (just because AS3 doesn't include a "char" data type...)
However, in the other class, I have several hidden values, like populated arrays, which I don't want accessible in the constructor to the user, yet I still want to be able to keep those variables when the class is cloned. :sigh:
Again, and again, and again, ActionScript lacks some very convenient capabilities...
[MuG]
January 25th, 2010, 09:40 AM
Again, and again, and again, ActionScript lacks some very convenient capabilities...
And still everyone uses it :)
You're right its a load of rubbish but if its what people are paying you to use then you learn shortcuts.
In my last job we had a few flash developers that used to develop in Java. They always try to apply proper coding practises and design patterns to Flash and in most cases you ALWAYS had to take some shortcuts and apply some strange nuance to it.
It fails at being a "proper" language no doubt.
Shaedo
January 25th, 2010, 10:54 AM
If it could be done I wonder if deciding which constructor to run might rival the inefficiency of converting back to a hexidecimal?
I wonder if you could simply check to see what is being put into the constructor and run it from there? eg
public function constructor(v1:int, v2:int = null, v3:int = null)
{
v2==null ? constructor1(v1) : constructor2(v1,v2,v3);
}
TheCanadian
January 25th, 2010, 03:59 PM
What you want to do is definitely impossible but here's a Colour class I made a few years ago that may give you ideas:
package {
public class Colour extends Object {
private var n:uint;
public function Colour(n:uint = 0) {
if(n > 0xFFFFFFFF) throw new RangeError("Colour cannot be represented by a value greater than 0xFFFFFFFF");
this.n = n;
}
public function get alpha():uint {
return (this.n >> 24) & 0xFF;
}
public function set alpha(n:uint):void {
if(n > 255) throw new RangeError("Colour channel cannot exceed 255");
this.n = n << 24 | this.red << 16 | this.green << 8 | this.blue;
}
public function get red():uint {
return (this.n >> 16) & 0xFF;
}
public function set red(n:uint):void {
if(n > 255) throw new RangeError("Colour channel cannot exceed 255");
this.n = this.alpha << 24 | n << 16 | this.green << 8 | this.blue;
}
public function get green():uint {
return (this.n >> 8) & 0xFF;
}
public function set green(n:uint):void {
if(n > 255) throw new RangeError("Colour channel cannot exceed 255");
this.n = this.alpha << 24 | this.red << 16 | n << 8 | this.blue;
}
public function get blue():uint {
return this.n & 0xFF;
}
public function set blue(n:uint):void {
if(n > 255) throw new RangeError("Colour channel cannot exceed 255");
this.n = this.alpha << 24 | this.red << 16 | this.green << 8 | n;
}
public function get hex():uint {
return this.n;
}
public function set hex(n:uint):void {
if(n > 0xFFFFFFFF) throw new RangeError("Colour cannot be represented by a value greater than 0xFFFFFFFF");
this.n = n;
}
public function valueOf():uint {
return this.n;
}
public function toString(radix:uint = 16):String {
return this.n.toString(radix).toUpperCase();
}
public function offset(n:uint, a:Boolean):void {
if(a) {
var da:int = this.alpha + n;
if(da > 255) this.alpha = 255;
else if(da < 0) this.alpha = 0;
else this.alpha = da;
}
var dr:int = this.red + n;
if(dr > 255) this.red = 255;
else if(dr < 0) this.red = 0;
else this.red = dr;
var dg:int = this.green + n;
if(dg > 255) this.green = 255;
else if(dg < 0) this.green = 0;
else this.green = dg;
var db:int = this.blue + n;
if(db > 255) this.blue = 255;
else if(db < 0) this.blue = 0;
else this.blue = db;
}
public static function fromARGB(a:uint, r:uint, g:uint, b:uint):Colour {
if(a > 255 || r > 255 || g > 255 || b > 255) throw new RangeError();
var temp:Colour = new Colour();
temp.alpha = a, temp.red = r, temp.green = g, temp.blue = b;
return temp;
}
}
}
Krilnon
January 25th, 2010, 04:21 PM
Technically integers can't be null… but it's true that you could use cardinal values (of sorts) in this specific situation. For example:
public function Color(r:uint = 0, g:uint = 0, b:uint = 0):void
{
if(arguments.length == 1){ // by convention, this could be a hint that r uses more than the first byte of the uint
_value = r;
} else {
//Converting from RGB to hex is slow and inefficient.
_value = RGBtoHEX(r, g, b);
}
}
Anyway, I agree that it might be nice to be able to have private constructors or something… oh well.
AS3 only allows one constructor, right?
I think this might not actually be Adobe's fault, originally. I think that it was in the ECMAScript 4 draft for some reason or another. So, that means that the constructor issue might have been instigated by some party other than Adobe. Now that ES4 is basically dead, there's no real reason why ActionScript has to conform to it anymore, so you could blame them for not changing the language in the time that has passed since it became clear that ES 3.1/5 was going to be the standard for JS instead of ES4.
There's an interesting interview with Brendan Eich (the guy who authored JavaScript, mainly) where he talks about some of this stuff. He even talks about ActionScript a bit:
http://www.codersatwork.com/
It was definitely a collaborative effort and in some ways a compromise because we were working with Adobe, who had done a derivative language called ActionScript. Their version three was the one that was influencing the fourth-edition proposals. And that was based on Waldemar Horwat's work on the original JavaScript 2/ECMAScript fourth-edition proposals in the late '90s, which got mothballed in 2003 when Netscape mostly got laid off and the Mozilla foundation was set up.
Waldemar did a good job -- I gave him the keys to the kingdom in late '97 when I went off to found mozilla.org with Jamie. Waldemar is a huge brain -- I think he won the Putnam in '87. MIT PhD. He did try and keep the dynamic flavor of the language, but he struggled to add certain programming-in-the-large facilities to it, like namespaces.
Anyway, given the above information, it seems like a lot of people had their hands and respective interests in the creation of both AS3 and ES4, so I can see how it was jumbled up in some respects.
TheCanadian
January 25th, 2010, 04:42 PM
You're like the new senocular :P Where is he, anyways?
Krilnon
January 25th, 2010, 05:06 PM
Rochester, NY, of course.
I have been wondering about that myself! He hasn't posted in more than a month.
mathew.er
January 25th, 2010, 08:22 PM
I guess we won't have that until there's a whole method overloading implementation in AS4 or something. :)
theCodeBot
January 25th, 2010, 11:34 PM
You're like the new senocular :P Where is he, anyways?
Ya know, I have also noticed that Trevor seems to have vanished. His site has seen a couple of updates lately, so I don't think his godly ethernet cable was unplugged... Not sure.
Though I'm pretty sure Krilnon covered this one anyways :P
I had read the entire OP and startign mentally formulating the words of my reply, then BOOM, there's theCanadian and Krilnon to rain on my parade again 0.o
TheCanadian
January 26th, 2010, 01:05 AM
Raining on parades is what I live for!
Powered by vBulletin® Version 4.1.10 Copyright © 2012 vBulletin Solutions, Inc. All rights reserved.