A Way to implement Abstract Class In Flex

來源:互聯網
上載者:User

A Way to implement Abstract Class In Flex

It’s a fact that, until now(3.0) the ActionScript doesn’t implement the
abstract class, it has Interface, but the abstract class is very useful when
you have some logic that is fixed, and these class extends the class have some
same methods(logic), and some other methods should be implemented in the
subclasses, we should prevent the customer(of the super class) instantiating
the super class. Compare to Interface, the abstract emphasize the “extending”,
which means code reusing. But the Interface is more flexiable.

Okey, I found an article which introduce a way to implement the abstract
class, but the way is not that perfect, it can implement the “Abstract” in
runtime, it can’t check the error in complie time if the customer(of the super class)
try to new the instance of the super class.

And, the runtime
error is not recommended. There is no free lunch, to Force the AS3 to do
something which is not native may cost a lot, In this case , you should do think
carefully in your projects.

The following
are copied from http://joshblog.net/2007/08/19/enforcing-abstract-classes-at-runtime-in-actionscript-3/,
by JOSH TYNJALA.

As you probably know, abstract classes are not a language feature of ActionScript 3. If you are unfamiliar with
the concept of an abstract class, let me explain. Think of an abstract class as
a super-powered interface. It defines a series of functions that must be
implemented, and it cannot be instantiated directly. It goes a step beyond an
interface because it also defines some functions that are already fully
implemented.

To use an
analogy, all electronic devices generally have the same connector to plug into
the wall. However, not all electronics have the same purpose. A coffee maker
and a DVD player do very different things. We could make an interface
IElectronicDevice to make sure they all have a plugIntoWall() function, but
then every device will need to re-implement the common wall plug functionality
that doesn’t differ very often. By making a class AbstractElectronicDevice, we
can implement the wall plug functionality once, and all subclasses of
AbstractElectronicDevice will be able to use it without re-implementing the
same code.

The problem, of course, is that the
coffee maker and DVD player have different controls for turning power on and
off. The coffee maker might have a switch, while the DVD player has a button.
We can’t implement the togglePower() function in AbstractElectronicDevice
because many electronics will have different controls, so we need some way to
force all subclasses of AbstractElectronicDevice to implement this function
themselves. Using the methods developed to enforce Singletons in ActionScript 3 as a guide, I’ve found a way to enforce the abstractness of a class at
runtime upon instantiation.

There are two
main parts to enforcing an abstract class. First, we must stop a developer from
instantiating the abstract class directly. To do this, the constructor needs a
little special sauce. Since anyone can create an instance of a public class by
simply using the new keyword, we need the constructor of our abstract class to
require a parameter that only subclasses will be able to pass. Second, we must
ensure that a developer implements functions that the abstract class has
defined, but not implemented.

Stopping Direct Instantiation of an Abstract Class

The magic bean
to stop a developer from instantiating a class directly is one keyword: this. You don’t have access to an instance
of a class until after you call a constructor, so only an instance of a
subclass will be able to pass a reference to itself to the super class. Let’s
look at some code to help make things clearer.

The instance of
MyAbstractType expects to receive a reference to itself as the first parameter
in the constructor. If it does not, an error will be thrown.

package com.joshtynjala.abstract

{

    import
flash.errors.IllegalOperationError;

 

    public class MyAbstractType

    {

       public function
MyAbstractType(self:MyAbstractType)

       {

           if(self != this)

           {

              //only a subclass can pass a valid reference to self

              throw new IllegalOperationError("Abstract class did not receive reference to self.
MyAbstractType cannot be instantiated directly."
);

           }

       }

    }

}

Only MyConcreteType and other subclasses
of MyAbstractType will be able to pass a reference to the instance to their super() constructors. Notice that users of
MyConcreteType don’t need to know that it extends an abstract class. The
signature of the MyConcreteType’s constructor can be completely different than
MyAbstractType.

package com.joshtynjala.abstract

{

    public class MyConcreteType extends
MyAbstractType

    {

       public function MyConcreteType()

       {

           //pass "this" to clear the abstract check

           super(this);

       }

    }

}

 

Forcing Implementation of Functions in
Subclasses

Next, like with an interface,
we need to force subclasses of our abstract class to implement specific
functions. Ideally, we want this enforcement to happen immediately when the
object is created (to make bugs visible as early as possible). After we check
that the user isn’t trying to instantiate the abstract class directly, we
should check to be sure the unimplemented methods are overridden. We can do by
checking the results from theflash.utils.describeType() function against a list of unimplemented methods in the abstract
class. Again, a little code should give us a clearer picture.

In MyAbstractType, after we check for a reference to the self
parameter, we build a list of unimplemented functions in an Array. Next, we use describeType()to get a list of the methods declared in the instance. If a
subclass of MyAbstractType overrides a method, the declaredBy attribute in the method XML will specify the name of the
subclass rather than MyAbstractType.

package com.joshtynjala.abstract

{

    import flash.errors.IllegalOperationError;

    import flash.utils.describeType;

    import
flash.utils.getQualifiedClassName;

 

    public class MyAbstractType

    {

       public function
MyAbstractType(self:MyAbstractType)

       {

           if(self != this)

           {

              //only a subclass can pass a valid reference to self

              throw new IllegalOperationError("Abstract class did not receive reference to self.
MyAbstractType cannot be instantiated directly."
);

           }

 

           //these functions MUST be implemented in subclasses

           var unimplemented:Array = [mustBeOverridden];

 

           //get the fully-qualified name the abstract class

           var abstractTypeName:String =
getQualifiedClassName(MyAbstractType);

 

           //get a list of all the methods declared by the abstract class

           //if a subclass overrides a function, declaredBy will contain the
subclass name

           var selfDescription:XML = describeType(this);

           var methods:XMLList =
selfDescription.method.(@declaredBy == abstractTypeName &&
unimplemented.indexOf(this[@name]) >= 0);

 

           if(methods.length() > 0)

           {

              //we'll only get here if the function is still unimplemented

              var concreteTypeName:String =
getQualifiedClassName(this);

              throw new IllegalOperationError("Function " + methods[0].@name + " from
abstract class "
+
abstractTypeName + " has not
been implemented by subclass "
+ concreteTypeName);

           }

       }

 

       //implemented

       public function alreadyImplemented():void

       {

           trace("Don't forget to list me in the Array of valid functions.");

       }

 

       //unimplemented

       public function
mustBeOverridden(param:String):void {};

    }

}

 

Now, in MyConcreteType, we can implement
the mustBeOverridden() function. If we do not, an error will be
thrown. To be certain, try commenting out the implementation of mustBeOverridden() in MyConcreteClass. If you instantiate
it, you will receive a runtime error.

package com.joshtynjala.abstract

{

    public class MyConcreteType extends
MyAbstractType

    {

       public function MyConcreteType()

       {

           //pass "this" to clear the abstract check

           super(this);

       }

 

       //implemented

       override public function
mustBeOverridden(param:String):void

       {

           trace("param:", param);

       }

    }

}

Conclusions

As you probably noticed, the first part of implementing an
abstract class is very simple. Making the abstract class receive a reference to
itself enforces subclassing, and it can be done in only a few lines of code.
The second part, making an abstract class work like an interface, requires a
lot more code, and it may be more prone to errors. You, as a developer, must
remember to add all the unimplemented methods to the Array in the constructor.
Additionally, if the class gets large, I can imagine that calling describeType() often enough could lead to performance problems. In most cases,
as long as you keep your classes clean, it should work well. I highly recommend
the subclass enforcement, but I wouldn’t be heartbroken if you feel that
checking for unimplemented methods is overkill.

Source
code for this tutorial is
available for download. It includes all the code above plus an extra
implementation (for comparison) of the “electronic device” example I described
at the beginning. It’s all under the terms of the MIT license.

 

Yes, it is really
a good idea to implement the “Abstract Class”, but the checking is postponed to
runtime, then some defects appear:

  1. Cost

May be it costs too much, you have to call describeType, this is really
costing, especially when you have to create a lot of instances of subclasses.

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.