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

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)

Related

How to Initialize Interface In Flex?

I'm new to Flex. I have some doubt regarding Interface in Flex. As we know AS3 is also an Object Oriented Language.
Questions are :
1.if class A extends Class B. Then Class A can't implements interface C. Why ?
The class which don't extends other class can implement the interface. What is the reason behind that ?
why we can't give access specifier to the functions declaration in Flex Interface ?
Why can't we write like
class A extends class B implements C
Updates Of My Question with Code
Interface Part ->
package
{
public interface InterfaceTesting
{
function foo():void;
}
}
Class A ->
package
{
import mx.controls.Alert;
public class A
{
public function test():void
{
trace("control is in Top Class")
Alert.show("control is in Top Class");
}
}
}
Class B ->
package
{
import mx.controls.Alert;
import mx.messaging.channels.StreamingAMFChannel;
import mx.states.OverrideBase;
public class B extends A implements InterfaceTesting
{
override public function test():void
{
Alert.show("We are in Second Class");
}
public function foo():void
{
Alert.show("This is Interface Implementation");
}
}
}
I'm getting an Error in class B. which is 1024- Overriding a function which is not marked for override.
Please Guide me.
I'm not entirely sure what you're asking, but what you're describing should be possible.
A valid example:
ClassA.as
package {
public class ClassA extends ClassB implements InterfaceC {
public function ClassA() {
}
public function bar():void {
}
}
}
ClassB.as
package {
public class ClassB {
public function ClassB() {
}
public function foo():void {
}
}
}
InterfaceC.as
package {
public interface InterfaceC {
function foo():void; // Will be inherited from ClassB
function bar():void; // Is defined in ClassA
}
}
Edit: Regarding your third question:
To comply with an interface, the methods defined in the interface needs to be either public or internal. This is because an interface is useful only for declaring what methods are available publicly.
If your class implements InterfaceC (above) and contains the function foo() but has declared it private - it cannot be reached externally and hence won't comply with the interface.

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
}
}
}

AS3 override public function both are called?

I am a little confused by this concept.
If I override a public function in a base class, I would have thought that this override function is called and the original is ignored? though this doesn't seem to be the case...
public class AbstractScreen extends Sprite
{
public function AbstractScreen()
{
}
public function updateLanguage():void
{
trace("WARNING: need to override public function updateLanguage()");
}
}
public class Start extends AbstractScreen
{
override public function updateLanguage():void
{
title.text = _model.language.start
title.setTextFormat(titleFormat);
}
}
public class ViewManager extends Sprite
{
private var _model:Model;
private var _screens:Array;
public function ViewManager(model:Model)
{
_model = model;
_model.addEventListener(AppEvent.INIT_VIEW, initViews);
_model.addEventListener(AppEvent.UPDATE_VIEW, updateView);
_model.addEventListener(AppEvent.CHANGED_LANGUAGE, changeLanguage);
}
private function initViews(e:AppEvent):void
{
trace("View Manager: initViews");
_screens = new Array(new Start(_model), new TakePhoto(_model));
dispatchEvent(new ViewEvent(ViewEvent.VIEW_READY));
}
private function changeLanguage(e:AppEvent):void
{
for each (var screen:AbstractScreen in _screens)
{
screen.updateLanguage();
}
}
}
If my model dispatches a CHANGED_LANGUAGE event, the text in the views gets updated, But I also get a trace of "WARNING: need to override public function updateLanguage()" What could I be doing wrong?
You are right, this should not call the base class function. Are you sure there is no call to
super.initLanguage()
within your override?
Most IDE's add this call in the function body automatically, if they create an override for you.
EDIT
From your edit I see your are iterating over two objects of the types Start and TakePhoto. I assume TakePhoto is also derived from AbstractScreen and the trace may be comming from this one.
Also I suggest to use the abstract base class in your iteration.
for each (var screen:AbstractScreen in _screens)
{
screen.updateLanguage();
}

AS3 - Abstract Classes

How can I make an abstract class in AS3 nicely?
I've tried this:
public class AnAbstractClass
{
public function toBeImplemented():void
{
throw new NotImplementedError(); // I've created this error
}
}
public class AnConcreteClass extends AnAbstractClass
{
override public function toBeImplemented():void
{
// implementation...
}
}
But.. I don't like this way. And doesn't have compile time errors.
abstract classes are not supported by actionscript 3. see http://joshblog.net/2007/08/19/enforcing-abstract-classes-at-runtime-in-actionscript-3/
the above reference also provides a kind of hackish workaround to create abstract classes in as3.
Edit
also see http://www.kirupa.com/forum/showpost.php?s=a765fcf791afe46c5cf4c26509925cf7&p=1892533&postcount=70
Edit 2 (In response to comment)
Unfortunately, you're stuck with the runtime error. One alternative would be to have a protected constructor.... except as3 doesn't allow that either. See http://www.berniecode.com/blog/2007/11/28/proper-private-constructors-for-actionscript-30/ and http://gorillajawn.com/wordpress/2007/05/21/actionscript-3-%E2%80%93-no-private-constructor/.
You may Also find these useful: http://www.as3dp.com/category/abstract-classes/ and, in particular, http://www.as3dp.com/2009/04/07/design-pattern-principles-for-actionscript-30-the-dependency-inversion-principle/
package
{
import flash.errors.IllegalOperationError;
import flash.utils.getDefinitionByName;
import flash.utils.getQualifiedClassName;
import flash.utils.getQualifiedSuperclassName;
public class AbstractClass
{
public function AbstractClass()
{
inspectAbstract();
}
private function inspectAbstract():void
{
var className : String = getQualifiedClassName(this);
if (getDefinitionByName(className) == AbstractClass )
{
throw new ArgumentError(
getQualifiedClassName(this) + "Class can not be instantiated.");
}
}
public function foo():void
{
throw new IllegalOperationError("Must override Concreate Class");
}
}
}
package
{
public class ConcreteClass extends AbstractClass
{
public function ConcreteClass()
{
super();
}
override public function foo() : void
{
trace("Implemented");
}
}
}
In AS3 would just use interfaces to make sure all functions are implemented at compile time.
I know it different but does the trick for an example such as the one above.
As long as they don't permit non-public constructors in actionscript, you'd have to rely on run time errors for abstract classes and singletons.