[AS3] OOP Question

21 posts

Flag Post

Hey guys, I just started to migrate to AS3 (yes, I know its late), and I’m having trouble programming in OOP.

[CODE]
function generateItem(item:*)
{
var testItem:item = new item();
}
generate_btn.addEventListener(MouseEvent.CLICK , generateItem(solarbeam));

[/CODE]

I get a “Type was not found or was not a compile-time constant: item” error.

Heres what I’m trying to do:

Use the “generateItem” function to create a instance of whatever class the “item” parameter is. (eg. generateItem(item1), generateItem(item2), etc.)

I think the problem is Flash is reading “item” as a class instead of a parameter, and since I have no class named “item” , it comes up as a error.

If there is a better way of doing this, please let me know.

Any help is appreciated.

Thanks.

-Jephz

 
Flag Post

Well I’m not sure you can do that, mouseEvents by default accept events as parameters.

Let the buttons call functions that generateItems. Like this:

solar.addEventListener(MouseEvent.CLICK , onSolar);
beam.addEventListener(MouseEvent.CLICK , onBeam);
function onSolar(e:Event)
{
   generateItem("Solar");
}
function onBeam(e:Event)
{
   generateItem("Beam");
}
 function generateItem(item:String)
{
    var test:Item;
    switch(item)
    case("Beam"): test = new Beam(); break;
    case("Solar"): test = new Solar(); break;
}

IMO this is safer

 
Flag Post

If you’re the guy who also posted in newgrounds, do note that milchreis is a better approach. You can use a dictionary. However, my implementation is actually basically the same, only using case statements and generally targeted for a small amount of items.

 
Flag Post

Thanks for the reply, but I’m afraid this won’t work for me as I will have many many more items and a hundred different case statements doesn’t seem very practical.

 
Flag Post

And a hundred buttons with a hundred event listeners?

 
Flag Post

I don’t really understand what you are trying to do but If you could explain it a bit better I might be able to help.

(Also it’s never to late to learn AS3 :D)

 
Flag Post
Originally posted by Jephz:

[CODE]
function generateItem(item:*)
{
var testItem:item = new item();
}
generate_btn.addEventListener(MouseEvent.CLICK , generateItem(solarbeam));

[/CODE]

1. It’s <pre.> and </pre.> (without the dots), not [CODE] and [/CODE], please read the posting guidelines. We have stickies for a reason.

2. function generateItem(item:*) {} is not proper syntax, you’re missing the return type. Also, in writing it this way you have explicitly declared item to be an instance of an object class, not a class, which leads us to:

3. var testItem:item is pure nonsense. It’s not even readily apparent what you are trying to do. I don’t want to go all Pauli on you, but the closest I can get to making sense of your purpose in writing that function was that you were going for a roundabout
var item:SomeClass = new SomeClass();
and you obviously don’t need a separate function for that.

4. At this point we cross into the twilight zone. The second argument in the addEventListener call should be a function. What you have there (i.e. generateItem(solarbeam)) is likely not a function. I say likely because the generateItem function does not currently have a return type specified. Ultimately, once everything is fixed, it is conceivable that generateItem could return a value of type function, making generateItem(solarBeam) a valid argument. It’s just not very likely.

4bis. If that were the case though, you should be aware that whatever function generateItem(solarbeam) returns should take one and only one parameter, and can accommodate parameters of type MouveEvent because that’s what it’s going to be getting.

You really, really need to read the docs. Go read the sticky in this here forum about making games in Flash, go look up the resources, do some tutorials and start learning the basics. I strongly recommend ‘Hello World’ as a first step.

 
Flag Post

What is item? Is it a class? Are you trying to do:

function generateItem(itemClass:Class) : Item {
 return Item(new itemClass());
}

… where Item is some superclass of all the classes you can pass in?

Your event listener line doesn’t make much sense either.

 
Flag Post

Um, alright let me try to clarify things.

“solarbeam” is a class.

testItem is a instance of solarbeam that I would like to create.

“item” is a parameter , not a class.

For example, if I had two classes, Solarbeam_1 and Solarbeam_2.

I use generateItem(insert class here) , to create a instance of whatever class I inserted into the parameter.

So if I put, generateItem(Solarbeam_1) , it would create a instance of Solarbeam_1 , if I put Solarbeam_2 , it would create a instance of Solarbeam_2.

At least that is how I “think” it would work. My endgame is trying to create a OOP inventory system using classes, and it is my first time trying so maybe my logic of how its suppose to work isn’t correct. If so, I do appreciate a nudge into the right direction.

 
Flag Post

So I read that as

In a Main class you want to create a inventory item.
So in Main you create a inventory item
And depending on what that inventory item is – it has a different class applied to it.
And so you will have a new class for each inventory item and apply it to the corresponding item created?

Is this correct? If it is not then use psudo code to type out exactly what you want to do. If that is correct then you are going about this all wrong (or at least not how >I< would do it.

 
Flag Post
Originally posted by Jephz:

Um, alright let me try to clarify things.

“solarbeam” is a class.

testItem is a instance of solarbeam that I would like to create.

“item” is a parameter , not a class.

Hold it right here! item is a parameter, sure, but a parameter of what type? Is it an int, a Number, a Sprite, a Boolean, a String? No, it’s a Class, and by that I mean that the variable item is a pointer which refers to an object of type Class. Because that’s, by your own admission, the type of information you want it to convey. Two lines down from my quote, you seem to understand that when you write: “I use generateItem(insert class here) , to create a instance of whatever class I inserted into the parameter.”

What you say you want to do is roughly what BobJanova posted, but you seem confused as to how to achieve it because it looks like what you want to try to do is to feed an instance of a class to generateItem and have it return a new instance of the same class, which would be needlessly convoluted, and wasteful.

So what you want to do is:

function generateItem(whatClass:Class):* {return new whatClass();}

which you would then call with a line such as

var newItem:MyClass = generateItem(MyClass);

In case you can’t see it, this is just a convoluted way of doing

var newItem:MyClass = new MyClass();

with the added double whammy that it’s slower than just spawning a new object of the type you want and you’ve lost the option of having parameters in the constructor.

 
Flag Post

Ace, he seems to want “generateItem()” function to serve as an event listener and produce an instance of type corresponding to what triggered that function. It’s not this easy, and at least weird to have one function for all the classes, so I asked him about a hundred of buttons.

 
Flag Post

‘Seems’ being the keyword here. Is your understanding that Jephz wants to create an object when a button is clicked, but the class to which the object belongs is not set in stone? So that depending on which button is clicked, and presumably in what conditions, the class of the object created would vary?

Indeed that would be somewhat complex, if for no other reason that a function triggered by an eventListener, if it even can return a value (I doubt it, but I haven’t checked), will return a value that isn’t attached to anything. If you create an object inside such a function it will be collected as garbage because as soon as the function ends it won’t be accessible from anywhere anymore.

A roundabout I can see to solve the problem would be to add a class-level Array to the button that generates those objects. You’d then push() the new object into the Array and you can retrieve it further down the road.

Something like this:

package 
{
	import flash.display.SimpleButton;
	import flash.events.Event;
	import flash.events.MouseEvent;
	
	public class MonkeyButton extends SimpleButton 
	{
		private var label:Class;
		public var queue:Array;
		
		public function MonkeyButton():void
		{
			queue = [];
			this.addEventListener(Event.ADDED_TO_STAGE, activate);
		}
		
		private function activate(eve:Event):void
		{
			this.removeEventListener(Event.ADDED_TO_STAGE, activate);
			this.addEventListener(MouseEvent.CLICK, generateItem);
		}
		
		private function generateItem(eve:Event):void 
		{
			if (label) queue.push(new label());
		}
		
		public function setup(customClass:Class):void
		{
			label = customClass;
		}
	}
}

Note: I haven’t tested this class to see if it even compiles. I make no guarantee that it does. Please read this as pseudocode.

 
Flag Post

What vesperbot said , I think its close to what I am trying to achieve except the function doesn’t necessarily have to be triggered by a button. It can be triggered after another function runs, or by something else. The button is irrelevant to me right now, I can just put the function on the main timeline’s code.

I was hoping that I could have the item parameter to substitute for whatever class I decide to plug in later. Apparently, its not that simple.

How complex would it be if I wanted to achieve that?

As for the Aceblue’s pseudocode, I sort of understand how it works, but is all that really necessary?

I do appreciate all of you trying to help me out, so thanks a lot .

-Jephz

 
Flag Post
Originally posted by Jephz:

I was hoping that I could have the item parameter to substitute for whatever class I decide to plug in later. Apparently, its not that simple.

It is that simple and Bob gave you the code.

 
Flag Post

Well, you really can provide a parameter of type Class into a function. The trick is, you can’t supply an additional parameter for a function that’s designated as an event listener, it only accepts one parameter of type Event. If you need a function to be called at an event, then you might need a wrapper function like Secretmapper provided, both onSolar and onBeam are such wrappers.

 
Flag Post
Originally posted by Jephz:

What vesperbot said , I think its close to what I am trying to achieve except the function doesn’t necessarily have to be triggered by a button. It can be triggered after another function runs, or by something else. The button is irrelevant to me right now, I can just put the function on the main timeline’s code.

Nobody can help you if you yourself cannot tell what your problem is. Call back when you know exactly what you want and you are ready to lay down the specs of the problem in detail. I’m done.

 
Flag Post

Thanks for the reply, but I’m afraid this won’t work for me as I will have many many more items and a hundred different case statements doesn’t seem very practical.

Yup, that’s why I said you could use something like a dictionary. I only gave that as an example for a small amount of objects.

 
Flag Post

Oh man.

You are really just going about this all wrong. You need to separate out your event handling and your item creation. You want a dynamic thing that can make items for you, write that. Define its input. AFTER you’ve written that, write an event handler for mouse events. Let that function alone handle the logic whatever based on a mouse event. Then call your item creation object.

In other words, decouple more. And your original code is nonsense, like Ace_Blue said, it doesn’t at all work the way you think it does.

 
Flag Post
Originally posted by Jephz:

Thanks for the reply, but I’m afraid this won’t work for me as I will have many many more items and a hundred different case statements doesn’t seem very practical.

And this level of data management is when you need to build a content management system of some sort.

 
Flag Post
Originally posted by Secretmapper:

Well I’m not sure you can do that, mouseEvents by default accept events as parameters.

Let the buttons call functions that generateItems. Like this:

solar.addEventListener(MouseEvent.CLICK , onSolar);
beam.addEventListener(MouseEvent.CLICK , onBeam);
function onSolar(e:Event)
{
   generateItem("Solar");
}
function onBeam(e:Event)
{
   generateItem("Beam");
}
 function generateItem(item:String)
{
    var test:Item;
    switch(item)
    case("Beam"): test = new Beam(); break;
    case("Solar"): test = new Solar(); break;
}

IMO this is safer

I’d suggest cutting out the strings and case stuff, and try it like this instead:

solar.addEventListener(MouseEvent.CLICK , onSolar);
beam.addEventListener(MouseEvent.CLICK , onBeam);
function onSolar(e:Event)
{
   generateItem(Solar);
}
function onBeam(e:Event)
{
   generateItem(Beam);
}
 function generateItem(newItem:Class)
{
   var newItem:Item = new newItem(); // no case blocks needed for the same result. :D

   // ...rest of code here
}