Explicitly overriding constructors in ActionScript3 - actionscript-3

All,
I ran into this funny thing in a different post. It was pointed out to me that you can explicitly override a constructor... which doesn't seem necessary, and I am a little surprised it even compiles. Take a look:
public class TestClass
{
public function TestClass() {}
}
public class TestClass2 extends TestClass
{
public override function TestClass2() {}
}
Explicitly calling override on the constructor might just be a no-op, as it is certainly not necessary. My question: Is there a subtlety here that I am missing? Does explicitly overriding the constructor tell the compiler something?

public class TestClass
{
public function TestClass() {}
}
public class TestClass2 extends TestClass
{
public override function TestClass2() {
super();//this makes call to the default constructor
}

i think it's just a bit of freedom provided by as3 syntax :)imho bytecode of an swf with overriden contstructor is equal to one of swf with a normal one

Related

How to enforce derived classes to implement methods in AS3?

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.

AS3 Inheritance

When 'SubClass' extends 'SuperClass', when it inherit its methods and properties, it creates methods and properties that distinguishes from the 'SuperClass'?
Or if I create an instance of 'SubClass' and I try to modify a property, that was inherited from 'SuperClass', am I modificating the super class property also?
Thanks.
EDIT
package {
public class SubClass extends SuperClass {
public function SubClass() {
trace('superclass value n='+superClass.n+'\n');
trace('subclass changes inherited n'+'\n');
n = 3;
trace('subclass value n='+n+'\n');
trace('superclass value n='+superClass.n+'\n');
}
}
}
Returns me:
superclass value n=-1;
subclass changes inherited n;
subclass value n=3;
superclass value n=3;
I will explain it in short.
We have two classes - Subclass and SuperClass.
SuperClass have four methods:
private function methodPrivate():void;
protected function methodProtected():void;
public function methodPublic():void;
internal function methodInternal():void;
From the Subclass you:
Cannot access methodPrivate():void;
Can access methodProtected():void; but just like your private method, it means, you cannot access it from outside of Subclass.
Can access methodPublic():void; and everything can access if from outside of Subclass also.
methodInternal():void; is available for classes from the package of SuperClass.
You can however override these methods. Overriding doesn't change a methods of SuperClass but change them only in SubClass.
override public function methodPublic() : void {
// your additional code
super.methodPublic(); // eventually calling the same method of SuperClass, you can pass arguments to it also
}
As you know, your SuperClass can also have variables, that also can be public, protected, private or internal. You cannot override them, but you can do this with getters or setters however.
You can access variables that are created as public or protected by using a word "super" like this: super.someVariable .
So everything is up to you, if you want to create a different variables of the same name in SuperClass and SubClass, just declare one as private in SuperClass. If you want to have one variable that SuperClass and SubClass both can access - just declare it as protected or public.
Hope that was clear.
When you create a blank SubClass the extends SuperClass, you are creating a new class that provides the same interface (with the same implementation) to the parent class.
That is to say, if your parent class contains a method doSomething, your SubClass, without ever actually writing it, will have the doSomething method available as well. The one caveat to this is if the method is marked private, in which case the inheriting class, SubClass, will not have access.
package {
public class SuperClass {
public function SuperClass():void {
self.doSomething();
}
public function doSomething():void {
trace("doing something");
}
}
package {
import SuperClass;
public class SubClass extends SuperClass {
public function SubClass():void {}
}
}
Once you have this relationship established, you can decide whether calling doSomething on an instance of SubClass will behave differently than the default implementation, defined in SuperClass. If you want the same behavior, you leave it as is. If you want different behavior, then you override the parent class' method, using the keyword override.
package {
import SuperClass;
public class SubClass extends SuperClass {
public function SubClass():void {}
override public function doSomething():void {
trace("doing another thing instead");
}
}
}
Now something that calls doSomething on an instance of SubClass will get modified behavior. But the default implementation has not been touched. Instanced of SuperClass are not modified by this overriding of a method. Only instances of SubClass will be affected.
This is the same case for properties.
There is one exception to this, and that is static properties. A static property is a property of the class, not of an instance of the class. Static properties are not inherited. A static property looks like this:
package {
public class SuperClass {
public static var i:int = 0;
public function SuperClass():void {
}
public function doSomething():void {
trace("doing something");
}
}
The SubClass class will not have a reference to a static property i. However, a SubClass instance can change the static value of the SuperClass. As an example:
package {
import SuperClass;
public class SubClass extends SuperClass {
public function SubClass():void {}
override public function doSomething():void {
trace("changing something in SuperClass");
SuperClass.i = 1;
}
}
}
Now, the SuperClass's static variable i has a value of 1, instead of 0. In this way a SubClass has the potential (although it is the same potential any code has with the right access privileges) to change the properties of SuperClass.
I hope this helps.

t4mvc : Cannot inherit a controller class which has no default constructor?

I am using T4MVC with MVC2.
I have the following building blocks:
A simple entity interface which defines that every POCO entity must have a long Id property:
public interface IEntity
{
public long Id;
}
A simple POCO class which implements the IEntity interface and has some string properties:
public class CD : IEntity
{
public long Id { get; set; }
public long Name { get; set; }
}
A base controller:
public abstract class EntityController<T> : Controller where T : class, global::IEntity
{
public EntityController(IEntityManager<T> manager);
}
I use this base controller in my CDController (where CDManager implements the IEntityManager interface, which is a UnitOfWork pattern to add CRUD functionality):
public partial class CDController : EntityController<CD>
{
public CDController() : base(new CDManager()) { }
}
When I run my t4 template, this code is generated:
namespace MyApp.Web.Controllers {
public partial class CDController {
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
protected CDController(Dummy d) { }
But this gives me an error during compilation:
MyApp.EntityController<CD> does not contain a constructor that takes 0 arguments
How can I solve this?
I wanted by controller base class to be abstract and it's constructor protected and parametrized. Got around this issue by adding a blank constructor to ControllerBase that throws a NotImplementedException.
Doesn't quite feel right but it gets the job done. Only issue is when combined with dependency injection the wrong constructor will be called - since it throws an exception the app will bum out.
Code:
public abstract class ControllerBase : Controller
{
protected object AlwaysSupply { get; private set; }
public ControllerBase()
{
throw new NotImplementedException();
}
public ControllerBase(object alwaysSupply)
{
AlwaysSupply = alwaysSupply;
}
}
This will cause T4MVC to generate compilable code. The fault seems to be it always tries to generate a blank (no parameters) constructor for controller classes.
Hope this helps someone.
I see the problem, and it comes down to T4MVC not quite doing the right thing when dealing with generic classes. Normally it would generate a default ctor for it in a partial class, but the fact that it's generic is throwing it off.
You should be able to work around simply by adding a default ctor yourself, e.g.
public abstract partial class EntityController<T> : Controller where T : class, IEntity {
public EntityController() { }
// etc...
}
I've noticed something very odd:
I've added the empty constructor to the base class, but without the throw new NotImplementedException(); and it works fine.
But here's the odd thing, when calling the controller if I have an url like
/{controller}?params (default action being set to Index in the RouteConfig) the parameterless private controller on the base class is called.
But when I have an url like /{controller}/{action}?params then the constructor with parameters is called.

ActionScript: Determine wether superclass implements a particular interface?

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 :(

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.