1. Code
  2. ActionScript

Adding Multiple Inheritance to AS3 with Traits and Realaxy Editor

Read Time:5 minsLanguages:

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 1Figure 1Figure 1

Step 2

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

Figure 2Figure 2Figure 2

Step 3

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

Figure 3Figure 3Figure 3

Step 4

This code should be created:

Figure 4Figure 4Figure 4

Step 5

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

Figure 5Figure 5Figure 5

Step 6

Create a Speak interface with a single "speak" method.

Figure 6Figure 6Figure 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 7Figure 7Figure 7

Step 8

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

Figure 8Figure 8Figure 8

Step 9

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

Figure 9Figure 9Figure 9

Step 10

In the Creature class add a "Speak" interface to "implements".

Figure 10Figure 10Figure 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 14Figure 14Figure 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 16Figure 16Figure 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 17Figure 17Figure 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 18Figure 18Figure 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 19Figure 19Figure 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 20Figure 20Figure 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".

Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.