Interface that is also a Display Object - actionscript-3

I have some classes that implement an interface, but also extend the Sprite class:
package {
public interface IState {
function addMonster():void;
}
}
package {
public class Fuzzy extends Sprite implements IState {
public function addMonster():void {
}
}
}
package {
public class LizardSkin extends Sprite implements IState {
public function addMonster():void {
}
}
}
// Document class
package {
public class Main extends MovieClip {
private var state:IState;
public function Main():void {
state = new Fuzzy();
addChild(state);
}
}
}
When I try to addChild(state) I keep getting an error message 1067: Implicit coercion of a value of type IState to an unrelated type flash.display:DisplayObject.
Now I know I've seen examples where a class extends MovieClip / Sprite and implements an interface...what can I do to make it so I can add "state" to the stage but also implement the methods I want??

A simple cast should do it most of the time:
addChild(state as DisplayObject);
The compiler raises that error otherwise because it doesn't assume IState is always implemented by something that is a DisplayObject, but if you can guarantee that condition you can always cast.

What I do in situations like this is use an IDisplayable interface, that looks like this:
public interface IDisplayable
{
function get displayObject():DisplayObject;
}
and its implementation in a Sprite or MovieClip simply looks like this:
public function get displayObject():DisplayObject
{
return this;
}
Your IState objects could then be added to the stage using addChild(state.displayObject);, when your IState interface extends IDisplayable.

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)

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.

Actionscript 3.0 - Get variable from superclass to new object

How do I do this?
public class SuperClass extends MovieClip {
public static var test:String = 'Hello world';
}
public class SubClass extends SuperClass {
public function SubClass() {
var unit = new Unit();
addChild(Unit);
}
}
public class Unit extends MovieClip {
public function Unit() {
//Get variable:test from SuperClass??
trace(SubClass.test); //Error
}
}
Hope you understand what I want to do?
Want to get the variable 'test' from the SuperClass in my new Unit added in SubClass.
Thanks!
In this case your class named SubClass uses the Unit class through composition, not inheritance. As such the Unit class knows nothing about SubClass or SuperClass or any of their properties like the test property.
You can, however, pass a value into the Unit class through it's constructor (or just set a value directly onto a property of the Unit class):
(showing the last two classes only)
public class SubClass extends SuperClass {
public function SubClass() {
var unit = new Unit(test);
addChild(Unit);
}
}
public class Unit extends MovieClip {
private var test:String;
public function Unit(test:String) {
this.test = test;
}
}
[Edit]
Since your Unit class needs to access many properties of SubClass (and/or SuperClass), you might want to just pass an instance of SubClass to Unit:
public class SubClass extends SuperClass {
public function SubClass() {
var unit = new Unit(this);
addChild(Unit);
}
}
public class Unit extends MovieClip {
private var subClass:SubClass;
public function Unit(subClass:SubClass) {
this.subClass = subClass;
trace(subClass.text);
}
}
How you actually solve this depends on your use case. But there is no fundamental shortcut to do what you are asking.

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.