Values with several types

If you are experienced in OOP, you may wonder how this is possible, but chances are that you already know about it.

Defining a type

In haXe, every time you write a class, an enum, an interface, or a typedef, you are defining a new type. This type has the same path (the same name) as the class, enum, interface, or typedef you are writing.

Inheritance

In haXe, a class can extend another class. In such a case, not only does it have all of the fields (that is properties and functions) of all its parent classes, but also all the types that its parent classes have (in addition to its own type).

What that means is that, for example, when a function wants a parameter of type A, if B extends A, you can pass an instance of B to your function. This is illustrated in the following code:

class Main
{
public static function main()
{
var human : HumanBeing;
human = new HumanBeing("Benjamin");
congratulate(human);
}
public static function congratulate(lt : LivingThing)
{
trace("Congrats " + lt.name);
}
}
class LivingThing
{
public var name : String;
public function new()
{
name = "";
}
}
class HumanBeing extends LivingThing
{
public function new(name : String)
{
super();
this.name = name;
}
}

Note how we can pass an instance of HumanBeing where a variable of type LivingThing is expected?

Multi-inheritance

haXe does not support any kind of multi-inheritance. Although this has already been discussed on the haXe mailing list, this proposal has been rejected until now in order to keep the language pretty simple, because it's a generally misused concept and also because haXe has to target several languages and there are not many languages that allow the use of multi-inheritance. Note that it does not necessarily mean that haXe would not be able to simulate it in those languages, but it would certainly have a severe impact on performance.

Implementing an interface

There's another way to have values with several types: using interfaces.

Interfaces are only a description of what a class should implement to have a certain type. In this case, instead of using the extends keyword, we will use the implements keyword. In addition, each class implementing an interface needs to have its own code for the method defined.

Let's see an example by extending the LivingThing and the HumanBeing example. We all know that some living things in our world are capable of making noise, let's see how we can describe that with an interface:

interface INoiseAble
{
public function makeNoise() : Void;
}

This is a pretty simple example and the interface could for sure be more complex. Now, we all know that the HumanBeing is able to make noise; so, let's write it:

class HumanBeing extends LivingThing, implements INoiseAble
{
public function new(name : String)
{
super();
this.name = name;
}
}

Notice the comma before the implements keyword. It is important not to forget it, otherwise you may be wondering why the compiler tells you that there is an "unexpected implements" for a long time.

If you try to compile the code now, you will get an error saying: "Field makeNoise needed by INoiseAble is missing". Well, it is pretty self-explanatory: it simply means that we forgot to write the code for our HumanBeing to make some noise:

class HumanBeing extends LivingThing, implements INoiseAble
{
public function new(name : String)
{
super();
this.name = name;
}
public function makeNoise() : Void
{
trace("Hello.");
}
}

Now, you can compile the code without any error. Now, let's modify our Main class, so that it can take any INoiseAble value and make it make some noise:

class Main
{
public static function main()
{
var human : HumanBeing;
human = new HumanBeing("Benjamin");
makeNoiseWith(human);
}
public static function congratulate(lt : LivingThing)
{
trace("Congrats " + lt.name);
}
public static function makeNoiseWith(val : INoiseAble)
{
val.makeNoise();
}
}

Now you can compile without any problems. We are able to pass the human variable as an argument to makeNoiseWith because the HumanBeing class implements INoiseAble; therefore, the value of human is also of type INoiseAble. This is called "polymorphism".

Note

Note that interfaces cannot be extended, but an interface can "implement" another interface.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
13.58.120.57