Functions and variables disappearing of scope when using package - actionscript-3

In the document class, I got the following code:
package {
...
public class Main extends Sprite {
public function Main(){
...
model:IModel = new Model();
controller:IController = new Controller(model);
var controls:CompositeView = new Controls(model,controller)
//Accessing controls.x provokes 1202: Access of undefined property x in package view
}
}
}
Where class CompositeView is a extension of Component which in turn extends Sprite.
Component:
package view
{
....
public class Component extends Sprite
{
...
}
}
CompositeView:
package view
{
....
public class CompositeView extends Component
{
...
}
}
Controls:
package view
{
....
public class Controls extends CompositeView
{
...
}
}
But unfortunately, when I try to access controls.x I get a undefined property error.
Changing the package for all classes to the same name fixed this issue. E.g use package for everything instead of package and package.view.
What can be done in Actionscript to keep code organization and avoid this issue ?
Problem solved: var controls was used as a package name, changing name of the variable solved.

Related

How to make a public method that is not inherited by subclasses?

As the question states, I want to know how I can make a function in a class that other classes can access, but subclasses cannot. I have a class that has some public getters and setters that I want my document class to have access to call, but I don't want the subclass to have these functions because they'd be useless on the subclass.
For example
public class SomeClass
{
public function SomeClass() {}
public function notInherited():void { trace("Not inherited"; }
}
public class OtherClass extends SomeClass
{
public function OtherClass()
{
notInherited(); //Want this to return an error
}
}
public class HasAccess
{
public function HasAccess()
{
notInherited(); //Not inherited
}
}
I know this probably has something to do with custom namespaces, but after searching up about them I still don't really have much understanding of how they work. That's about it; thanks for reading.
You can't do this quite in the general terms you've asked, but you can do this if you put your document class and your other class in the same package and use internal instead of public, and you put your sub-class in a different package. The internal keyword limits access to classes in the same package.
Example (notice the package statements):
package main {
public class Main extends MovieClip {
public function Main() {
var stuff:Stuff = new Stuff();
stuff.doStuff();
}
}
}
package main {
public class Stuff {
internal function doStuff():void { }
}
}
package other {
public class OtherStuff extends Stuff {
public function OtherStuff() {
// no access to this.doStuff()
}
}
}
As for using a namespace, this can be a good option to make the intent of your code more clear, but it doesn't actually limit access in any new way, it just requires access to be more deliberate: while the namespace does hide visibility of the API to anyone who doesn't use the namespace, anyone can use the namespace and have access to the API without any additional limits (ie public, internal and protected).
Still, this may be all you are after. Here's an example which uses a public namespace and no packages:
// my_stuff.as
package {
public namespace my_stuff;
}
// Stuff.as
package {
public class Stuff {
my_stuff function doStuff():void { }
}
}
// Main.as
package {
import flash.display.MovieClip;
public class Main extends MovieClip {
public function Main() {
use namespace my_stuff; // you can put this above the class to give the entire class access to the namespace
var stuff:Stuff = new Stuff();
stuff.doStuff();
}
}
}
// OtherStuff.as
package {
public class OtherStuff extends Stuff {
public function OtherStuff() {
this.doStuff(); // not allowed
this.my_stuff::doStuff(); // allowed
// also allowed
use namespace my_stuff;
this.doStuff();
}
}
}
(Note that if your namespace is in a package, ex package stuff { public namespace my_stuff }, you must import the namespace just like a class, for example: import stuff.my_stuff)

Flash AS3 - Trying to access public function from another class throws error?

This is my Main.as:
package {
import flash.display.MovieClip;
public class Main extends MovieClip {
public function Main() {
// Code here
}
public function myFunc() {
trace('!!!!');
}
}
}
When I try accessing it from another class using the following code, Flash throws me Error #2136:
package {
import flash.display.MovieClip;
import Main;
public class MyClass extends MovieClip {
public var m:Main;
public function MyClass() {
m = new Main();
m.myFunc();
}
}
}
EDIT: One more thing. The second class is attached to a MovieClip and exported on the first frame. I thought it made no difference, but someone in the comments have told me it does and apparently that's what's causing the error in the first place. In that case, how can I access the public function from a class attached to a MC?
Next time post the error message itself, most of us do not have Flash errors memorized by id. ;)
From the docs:
2136 The SWF file %1 contains invalid data.
This rings a bell for me. Your Main class is probably your document class. The document class is a special class that cannot be instantiated.
To access properties and methods of the document class instance from other code, you simply need a reference to the document class instance.
There are many ways you could get a reference, as it is really just a code dependency design question. Two common, easy solutions are:
1. Use the root property of any display object that is added as a child of the document class instance. Since the root property is typed to DisplayObject you need to cast to your document class to access its methods and property, for example: Main(root).myFunc().
2. Use the singleton pattern and assign a static public reference to the document class instance:
public class Main {
public static var main:Main;
public function Main() {
main = this;
}
public function myFunc():void { }
}
// usage:
Main.main.myFunc();

AS3 undefined function #1006

I have a parent class called 'main.as'. I am trying to get the child class to call main's function. They both reside in the same folder.
// main.as //
package {
public class main extends MovieClip {
public function main() {
var child:child_mc = new child_mc(this);
}
public function callFunction():void {
trace("Done it");
}
}
}
.
// child.as //
package {
import main;
public class child extends MovieClip {
private var main:MovieClip = new MovieClip();
public function child(main:MovieClip):void {
this.main = main;
main.callFunction();
}
}
}
This is the error I've been getting:
TypeError: Error #1006: callFunction is not a function.
so I tried doing a trace like this
trace(main.callFunction);
and it says undefined. Can someone tell me what I am missing. I get this feeling its a very basic thing that I have overlooked!
Your "child" package is defined as "main". I'm not even sure how it complied, let alone run to the point of showing the error message you got.
I believe the code below should do what you expected.
(I also took the liberty to rename the classes to use CamelCase (with initial caps) to adhere to best practices and to be easier to distinguish from variable names.)
Main.as
package {
public class Main extends MovieClip {
public function Main() {
var child:ChildMC = new ChildMC();
child.main = this;
}
public function callFunction():void {
trace("Done it");
}
}
}
EDIT: I just saw your comment that points out that child_mc is a MovieClip in the Library. I guess then that the child class is set as the Base Class of the child_mc?
If so, you cannot pass properties through the instantiator, you need to find another way to pass along the instance of the Main class to the Child class.
One way would be to add a setter, like the following:
Child.as (Base Class for ChildMC)
package {
public class Child extends MovieClip {
private var _main:Main;
public function Child() {
}
public function set main(main:Main):void {
this._main = main;
this._main.callFunction();
}
}
}

Actionscript: Classes inside Classes

i'm trying to create a flash game, but i'm having trouble with my classes. i'm importing the classes on the main script. they're imported okay, i've tested it all. but i dont know how to use classes inside another class
this is what i've got so far:
class Class.Player {
public static var self:MovieClip;
public static var bullet:Class.Bullet;
function controls() {
//Shoot
if (Key.isDown(Key.SPACE)) {
bullet = new Bullet(100, 100);
}
}
it loads the class and declares the variable, but it claims "Bullet" is not an existing method. it is an existing method, and it works when i call it from the main script.
also, do i need to declare the class like public static var bullet:Class.Bullet;? it's the only way that works for me but wondered if there's a better way?
It looks like you are having problems with the naming of your classes. You don't have to call your classes Class.Name. Just use Name.
In your case, you could have a file called
Player.as
With this content:
package {
import flash.display.MovieClip;
public class Player extends MovieClip {
public private var bullet:Bullet;
public function Player(){
//constructor
}
function controls() {
//Shoot
if (Key.isDown(Key.SPACE)) {
bullet = new Bullet(100, 100);
}
}
}
}
And then a file called
Bullet.as
With this content:
package {
import flash.display.MovieClip;
public class Bullet extends MovieClip {
public function Bullet(x:Number, y:Number){
//constructor
}
}
}
You can read more information about creating and using custom classes here: http://www.flashandmath.com/bridge/intro/class.html
You're putting your package information in the Class name. I have no idea how this is even compiling for you (especially given that Class is a reserved word.
Your files should look more like:
package somePackage {//somePackage instead of the reserved word Class you were using
import someOtherPackage.Bullet;
public class Player extends MovieClip {
public var bullet:Bullet;
public function Player():void {
super();
//other constructor logic here
}
}
}

Flash failing with a RSL library, when main class extends a class and implements an interface

I'm trying to load a RSL library into a flash animation developed with Flash CS5 IDE, that extends a custom class and implements an interface. I have reduced the problem to the simplest setup and find that I can have my main class extend another class or implement an interface, but not do both at the same time if I want to load an RSL.
I have a very simple class to extend:
import flash.display.Sprite;
public class MySprite extends Sprite
{
public function MySprite()
{
}
}
The main class with TestSymbol which is a symbol from the RSL library:
import flash.display.Sprite;
public class MainApp extends MySprite implements ITest
{
public var bug:TestSymbol = new TestSymbol();
public function MainApp()
{
addChild(bug);
}
//To meet interface requirements
public function test():void {
}
}
}
and a very simple interface
public interface ITest
{
function test():void
}
The RSL library is a very simple one too - just one symbol with a square drawing. It is specified in the actionscript settings.
Everything runs well if I change the MainApp class to:
public class MainApp extends MySprite
or
public class MainApp extends Sprite implements ITest
but if I want both I get the VerifyError: Error #1014 with MySprite not found and ReferenceError: Error #1065.
Any ideas?
I had the same problem. Actually it will continue with this error even if you are extending from a class in RSL which implements an interface from RSL.
It looks like the rsl needs some time to load and be interpreted by the player.
If you would use in a second frame classes or interfaces encapsulated in the rsl they will work fine. How so ever they are not working fine in the first frame.
My solution, related to my case was:
1) Main application using external lib rsl.swf.
2) A module application having main document class ModuleBase implementing IModule both encapsulated in rsl.swf, so module application was using also the extaernal lib rsl.swf.
3) Main application was loading module application and casting it to ModuleBase.
It looks like time needed by Main application to load module application swf it is enough to initialize/register types inside rsl.
Howsoever inside Flash IDE:
1) testing the module application, which has main document of a type extending ModuleBase, exposed by rsl, will end in the VerifyError: Error #1014
2) compiling the module application works just fine
3) compiling and testing the main application works just fine
Inside browser:
1) testing the module application is failing with VerifyError: Error #1014
2) testing the main application works fine
So my solution is to compile modules extending some external class and use them inside an application which has the RSL types already available.
I hope this will help somebody.
//RSL
package interfaces {
public interface IModuleFactory
{
//...
}
}
package app.models {
import interfaces.IModuleFactory;
public class ModuleBase extends MovieClip implements IModuleFactory
{
//...
}
}
//Module
package {
import app.models.ModuleBase;
// main document class
public class Module extends app.models.ModuleBase
{
//..
}
}
//somewhere inside Main application
protected function onModuleLoaded(event:Event):void
{
var lInfo:LoaderInfo = event.currentTarget as LoaderInfo;
setTimeout( function(){ extractFactory(lInfo); },200);
}
protected function extractFactory(lInfo:LoaderInfo):void
{
if( lInfo )
{
if( !(lInfo.content is ModuleBase) )
{
trace(lInfo.content ,' is not ModuleBase');
}
var m:DisplayObject = lInfo.content;
if( !(m is IModuleFactory) )
{
trace(m ,' is not IModuleFactory');
}
if(m)
{
var factory:Function = (lInfo.content as IModuleFactory).factory;
if( null != factory)
{
factories[key] = factory;
trace('module loaded',m,key);
dispatchEvent(new Event('moduleloaded'));
}else{
trace('could not get a reference to module factory!');
}
}else{
trace('could not cast to ModuleBase');
}
}else{
trace('could not get a reference to a LodearInfo!');
}
}
Thank you for explaining this. Your scenario seems slightly more complex with the module extending and implementing from RSL. In my case (the module class MainApp implements and extends non-RSL class/interface and just uses a class from RSL as a variable). Implementing the interface by a parent (like ModuleBase) class instead of the Module class works well. It doesn't even give me an error when testing in Flash IDE.