Adding Multiple Inheritance to AS3 with Traits and Realaxy Editor

Adding Multiple Inheritance to AS3 with Traits and Realaxy Editor

Tutorial Details
  • Program: Realaxy Editor Beta 10 (build 8144+)
  • Difficulty: Intermediate
  • Estimated Completion Time: 25 minutes

In this post you’ll learn about a language extension called Traits, a feature of a new Beta of RASE, a smart and modern IDE for Adobe Flash based on Jetbrains MPS. Traits will allow you to use multiple inheritance in your projects, so a class can effectively extend two other classes.

The sample project was created with ActionScript 3.0 with Traits language extension using Realaxy ActionScript Editor (RASE). If you want to do it the same way, RASE can be downloaded here (if you are new to RASE please follow the Beginners guide here)

Why Use Multiple Inheritance?

ActionScript is a modern object-oriented language. At the moment, actual OOP defenition and interpreting assume that multiple inheritance is a vicious practice. Thus, AS itself does not permit multiple inheritance, and only the using of interfaces provides an alternative. It’s all well and good, no need to argue.

However, sometimes it seems unbearable. It happens that owing to this missing feature we make our code too sophisticated or even probably messy.

For instance, we have a class Creature, which already extends Sprite. We want to teach it how to speak. "A proper OOP" imposes us to make a composition. So we need to:

  1. Create an ISpeaker interface.
  2. Add a speak() method to ISpeaker.
  3. Implement this interface with a Speaker class.
  4. The Creature class should be inherited from ISpeaker.
  5. Then add a delegate to the Creature class. The speak method would redirect calling of speak() to the delegate.
  6. Well, it’s done.

Let’s imagine we have multiple inheritance. Then we make a Speaker class, inheriting our Creature class from the Speaker. That’s all, folks.

Then, imagine our Creature should be able to do a lot things: to walk, to move arms and legs, to eat, to smile, to cry. Maybe also to fly. You never know what kind of requirements could become a part of the spec. As a result, we gain hundreds and thousands of lines of a “proper” OOP code, which is so redundant and verbose, that understanding its real purpose would be difficult even to its author.

We, skilled Flashers, understand that the situation described is purely artificial. Who would create a pack of interfaces for every aspect of behavior? Even if those would be applicable not only for Creature. Indeed, the real code would look different, not so pretty and learnedly, but closer to the real world – that is to say, simpler.

So it turns out that the best intentions of ECMAScript’s (and, later, ActionScript’s) designers to create a modern and correct OOP language accommodate badly for our everyday work.

Enough complaining! We have a tool to fix it. RASE. Realaxy ActionScript Editor. This solution is Traits, an AS3 language extension.

Let’s proceed to action.


Step 1

First, create a new project with testTraits module containing main-class Creature.

Figure 1

Step 2

Enter the project details as shown here, and click Next:

Figure 2

Step 3

Create a new class called Creature, in the package com.example:

Figure 3

Step 4

This code should be created:

Figure 4

Step 5

Import a traits language by pressing Ctrl+L (or Command+L).

Figure 5

Step 6

Create a Speak interface with a single “speak” method.

Figure 6

Step 7

The lower part of the window has two tabs, “Interface” and “Trait“.

Select the “Trait” tab (colored with gray) and click on the empty editors field. A dialog box appears, offering us to create a new trait.

Figure 7

Step 8

After “OK” a default implementation is created by editor. Note how this is now trait Speak rather than interface Speak:

Figure 8

Step 9

Add a body to the “speak” method: just trace “Hello!” to the console.

Figure 9

Step 10

In the Creature class add a “Speak” interface to “implements“.

Figure 10

Step 11

The editor added an "i" to the right of the interface name. It means that the interface has a default implementation — it has trait behavior.

Figure 11

Step 12

RASE recognizes such behavior and does not highlight any error when methods are added to class.

That’s it! Our Creature can talk now! Add a call of method speak() to a class constructor to prove it.

Figure 12

Step 13

Edit the run-configuration.

Figure 13

Step 14

You’ll see this dialog:

Figure 14

Step 15

Press the “+” button to add a new Configuration, and select ActionScript.

Figure 15

Step 16

Enter the details as shown here:

Figure 16

(This way we can be sure we’ll see the trace.)


Step 17

Run the compiled SWF. A "Hello!" message appears in the console.

Figure 17

Here’s what we obtain:

  1. Code of interface and of implementation are bound up with navigation tools and bookmarks in editor.
  2. Code is now well-organized. Every implementation has a name: an interface name + “Impl“.
  3. Boost of the usability. In a class that uses this behavior, we only add our interface to the implemented list.
  4. Keeping apples and oranges separate. Code of Creature class is not “littered” with excessive entities. We’ve just ordered the Creature to talk.

As a result, we have behavior that is really like multiple inheritance but stands on “proper and correct” OOP recommendations.


Step 18

Let’s see how it works, by looking at the code we’re actually generating.

Click “Build->Generate (obsolete)->Generate Text from Current Model“. The newly generated code of the Creature class appears in the Output window.

Figure 18

The code demonstrated above implements a classical composition. The trait language extension hides redundant entities and organizes relationships between code artifacts. In fact, we operate a “pure” OOP code.

Now we see a new fast and easy way to teach our Creature how to do everything. The main thing is the behavior: we apply the same ground rules to another classes.

Let’s do it in 5 minutes.


Step 19

Add some new traits — one for each limb — just as we did before:

Figure 19

Step 20

The Creature class gets now a lot of new skills, but its code remains easily-readable and clean. Without the Traits language extension it would be completely different:

Figure 20

It’s time to say goodbye. I’m waiting for your questions, suggestions and comments.

Remember, if RASE is new to you, please read the “Beginners Guide“.

  • http://flastar.ru/blog flastar

    Awesome article! Thx for share!

  • http://www.akwebgenius.com/blog Stacey Reiman

    Looks very cool, I need to find a way to use this kind of stuff with my current project. Thanks for the article.

  • pankaj kumar

    Thanks ! will use RASE soon :-)

  • http://zanuka.com Mike Delucchi

    Nice example, and RASE is cool for sure…

    I’m curious for more info and real-world examples/benefits. Would be great to do a side by side comparison though to further illustrate the benefits of using traits …. vs the traditional methods as3 coders use every day in IDE’s like FlashBuilder, FDT, etc… for example, how would traits help out in an as3 project using pureMVC framework for example.

  • djheru

    One of the fundamental tenets of good object-oriented programming is “favor composition over inheritance”. The key is to consider the relationship between the two objects. If it is a “has a” relationship, then composition is more appropriate. If it is a “is a” relationship, then inheritance is more appropriate. By using inheritance in this fashion, you are reducing flexibility and will be a lot more likely to code yourself into corners as you try to add new features.

    • djheru

      To expand on my comments above, let’s say that during runtime, the Creature object gains the ability to speak telepathically. With inheritance, your Speak class will have to need to be rewritten to incorporate this new implementation of the speak() method. With composition, you could simply replace the Speak class with a TelepathySpeak class at runtime (assuming they both implement the ISpeaker interface or both extend a parent class that does).

      • http://www.realaxy.com Eugene
        Author

        I agree completely with your arguments. I feel, you did not catch some important features. Traits language just realizes multiple inheritance through a composition. All the shortcomings of the multiple inheritance based on the class inheritance are nowhere in evidence here. The composition is just implemented in a more convenient way.

        The only thing you need is to add a trait in a list of implemented classes. The editor does the rest. Furthermore, it also provides some Typesystem checks that would help you avoid errors in extending classes by means of composition.

        We are also not alone in such approach. Exactly the same decision is used in the OOP language Groovy++ — http://code.google.com/p/groovypptest/wiki/Traits

  • Chris

    I agree with djheru because if the inheritance tree gets too deep, you create dependencies on the ancestor classes. That is if you change an ancestor, you have to then recompile every project that uses that class.

    The other thing about multiple inheritance is you haven’t discussed how you handle repeated inheritance. If you have class A with methods M1, M2 and you create a class B that inherits from A and you create a class C that also inherits from A and class C overrides method M2 then you create class D that inherits from classes B and C. How you handle the fact that D how has two method M1s and two but different method M2s? There are also cases where you want to have both methods but with different names, how do you handle that?

    Is there an Eclipse version these tools?

  • https://github.com/puppetMaster3/Gamina-Core Vic

    https://github.com/puppetMaster3/Gamina-Core

    Above is another Composition, but as a framework.