Is there any non-hacky way to determine wether a class' superclass implements a particular interface?
For example, assume I've got:
class A extends EventDispatcher implements StuffHolder {
protected function get myStuff():Stuff { ... };
public function getStuff():Array {
if (super is StuffHolder) // <<< this doesn't work
return super['getStuff']().concat([myStuf]);
return [myStuff];
}
class B extends A {
override protected function get myStuff():Stuff { ... };
}
How could I perform that super is StuffHolder test in a way that, well, works? In this case, it always returns true.
In this case you might have to define StuffHolder (and have it extend EventDispatcher) as a class and have getStuff as a public/protected function. You could then overload the getStuff function in class A, but not in class B.
package {
public class StuffHolder extends EventDispatcher {
function StuffHolder() {
}
protected function getStuff():Array{
return ["Default"];
}
}
}
package {
public class A extends StuffHolder {
function A {
super();
}
protected override function getStuff():Array {
return ["A"];
}
}
}
package {
public class B extends StuffHolder {
function B {
super();
}
}
}
I don't have the full picture to figure out why you'd need that kind of (weird and possibly broken) inheritance, but could you rephrase it to if (this is actually an A instance)?
If so, you could go with...
import flash.utils.getQualifiedClassName;
if (getQualifiedClassName(this) == 'A')
The thing is, the is operator should be used on object instances. And it works all the way up to object -- I mean, A is B is true for every A ancestor or interface implementation.
I think you could come up with a better structure for your classes, though.
This isn't that pretty.
I could do something involving introspection, getting the current class, finding its parent class, then checking to see if that implements the StuffHolder interface… But that seems pretty ugly :(
Related
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)
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.
I have a rather simple theoretical question regarding OOP (in AS3) that I don't know how to google:
I need something like an abstract class, which would require that dependant class implements some interface, like this:
Interface ISomething
{
public function somethingize(otherThing:type):void;
}
abstract public class AbstractSomething implements ISomething
{
public function AbstractSomething()
{
// ...
}
public function doSomething():void
{
//code here
// ...
this.somethingize();
// ...
}
}
Is the only way to achieve such a thing is to drop an "abstract" keyword, and move somethingize to SomethingWrapper (with an implementation of throwing an "unimplemented exception"), or is there some better way to model it?
ActionScript doesnt support Abstract classes (unfortunately).
I think there are a few techniques out there to try and mimic abstracts, but my way is too just throw errors in my abstract classes to stop them being used directly, eg:
public class AbstractSomething implements ISomething
{
public function AbstractSomething()
{
throw new Error("this is an abstract class. override constructor in subclass");
}
public function doSomething():void
{
throw new Error("this is an abstract class. override doSomething in subclass");
}
}
Without more information about the specific implementation, I would prefer composition over inheritance in this case, specifically dependency injection.
public interface ISomething {
function somethingize(thing:*):void;
}
public class SomeWorker {
private var _something:ISomething;
public function SomeWorker(something:ISomething) {
this._something = something;
}
public function doSomething():void {
// work
this._something.somethingize(obj);
// more work
}
}
Inherrited classes of SomeWorker could inject the correct implementation of ISomething for the work they need to do, or that dependency could be resolved somewhere else.
I have made an interface called IHero i implement in my hero.as3 class.
the hero class is written so it can be inheritted in a movieclip class to handle movement etc etc. But somehow i can't figure out how to code this with a good practice.
Maybe i am in the wrong direction.
I want to have a movieclip subclass, which will be a hero for instance.
Should i just implement the IHero in the hero class with the following methods, or is this to overkill? - I guess I am looking for an answer upon what should be in an interface and what should not. Here is the interface.
package com.interfaces
{
public interface IHero
{
//movement
function MoveLeft():void;
function MoveRight():void;
function MoveUp():void;
function MoveDown():void;
//in battle
function DoDamage(isCasting:Boolean):void;
function DoHeal():void;
function Flee():void;
function TakeDamage():void;
function IsAlive():Boolean;
function CheckDeath():void;
function Die():void;
}
}
I think you are on a right track, whether its the right one or the wrong one is always subjective. But if you do want to go down this road, I suggest you read this article by Mick West. Its a few years old, but its still very applicable.
I think you really have two distinct interfaces, but probably more
public interface IMoveable {
function moveLeft(obj:DisplayObject):void;
function moveRight(obj:DisplayObject):void;
function moveUp(obj:DisplayObject):void;
function moveDown(obj:DisplayObject):void;
function Flee(obj:DisplayObject);
}
public interface IFightable {
function doDamage(withWeapon:IEquipableWeapon);
function takeDamage(fromWeapon:IEquipableWeapon);
function get isAlive():Boolean;
function checkDeath():void;
function Die():void;
function doHeal();
function get health():Number;
}
Then....
public class SimpleMover implements IMoveable {
// The movement implementation
// for example:
public funciton moveLeft(obj:DisplayObject) {
obj.x = obj.x -= 10;
}
}
public class SimpleFighter implements IFightable {
// The fighting implementation
private var _health:Number = 100;
function doDamage(withWeapon:IEquipableWeapon) {
_health -= withWeapon.damage;
}
}
Then inject those into your subclass MovieClip for your Hero.
public class Hero extends MovieClip {
private var _mover:IMoveable;
private var _fighter:IFightable;
public function Hero(mover:IMoveable, fighter:IFightable) {
_mover = move;
_fighter = fighter;
}
}
Here you are using the Hero class as both Component Manager and Render component, which goes slightly against what West is talking about in the article, but I digress. But the idea is that your Manager (the Hero) becomes more or less an orchestrator, proxying calls back through to which ever component is applicable; calling methods on _mover and fighter to do your actual work.
There are several advantages using an approach like this, and some disadvantages. First, its more complex to set up; it requires you to really like about components and what each logical chunck of code is going to do. But on the other hand, it decouples your implementations from each other, makes it more testable, and reuseable. You can also swap out components at any time (compile-time or run-time for that matter), which gives you some flexability when creating new Entities.
But anyway, its just a suggestion of a slightly different paradigm that you seem to be flirting with. Maybe you'll get some mileage out of it. But definitely give the article a read, if you haven't already.
Also look into (like check out the API) for the Unity Engine which has a similar aggregation vs inheritance model where interfaces are key to abstraction.
Usually you will want a regular class definition that extends movieclip, then set your hero movieclip to use that class in the export for actionscript options. The interface is most likely not needed at all for your game.
Just to clarify - interfaces are implemented, not inherited. Therefore it does not matter what type of class you create that implements IHero. So to make a type of library class that implements Ihero, extend a display object like Sprite or MovieClip, and then use the implements keyword to indicate the class implements Ihero.
Add the Ihero methods, and you now have a display object class that implements iHero. It might look something like this (note no constructor function supplied)
package
{
import flash.display.Sprite;
import com.interfaces.IHero;
/**
* ...
* #author Zachary Foley
*/
public class MyDisplayObkect extends Sprite implements IHero
{
public function MoveLeft():void
{
// Add Implementation here;
}
public function MoveRight():void
{
// Add Implementation here;
}
public function MoveUp():void
{
// Add Implementation here;
}
public function MoveDown():void
{
// Add Implementation here;
}
//in battle
public function DoDamage(isCasting:Boolean):void
{
// Add Implementation here;
}
public function DoHeal():void
{
// Add Implementation here;
}
public function Flee():void
{
// Add Implementation here;
}
public function TakeDamage():void
{
// Add Implementation here;
}
public function IsAlive():Boolean
{
// Add Implementation here;
}
public function CheckDeath():void
{
// Add Implementation here;
}
public function Die():void
{
// Add Implementation here;
}
}
}
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.