Object Oriented Programming

Classes

We will quickly introduce the structure of classes that you might already be familiar with if you've done some OO programming before :

    package my.pack;
    /*
        this will define the class my.pack.MyClass
    */
    class MyClass {
        // ....
    }

A Class can have several variables and methods.

    package my.pack;

    class MyClass {

        var id : Int;

        static var name : String = "MyString";

        function foo() : Void {
        }

        static function bar( s : String, v : Bool ) : Void {
        }
    }

Variables and methods can have the following flags :

  • static : the field belongs to the Class itself and not to instances of this class. Static identifiers can be used directly in the class itself. Outside of the class, it must be used with the class name (for example : my.pack.MyClass.name).
  • dynamic: the field can be dynamically rebound.
  • override: the field is being overridden in a subclass.
  • public : the field can be accessed from outside of the class.
  • private : the field access is restricted to the class itself and to classes that subclass or extends it. This ensures that the class internal state is not accessible.
    By default, all fields are private. This corresponds to the keyword protected in most other languages such as Java, PHP

All class variables must be declared with a type (you can use Dynamic if you don't know which type to use). Function arguments and return types are optional but are still strictly checked as we will see when introducing type inference.

Non-static variables may not have an initial value. Static variables can have an initial value, although it is not required.

Constructor

The class can have only one constructor, which is the not-static function called new. This is a keyword that can also be used to name a class function :

    class Point {
        public var x : Int;
        public var y : Int;

        public function new() {
            this.x = 0;
            this.y = 0;
        }
    }

Constructor parametrization & overloading :

    public function new( x : Int, ?y : Int ) {
        this.x = x;
        this.y = (y == null) ? 0 : y; // "y" is optional
    }

Class Inheritance

When declared, it's possible that a class extends one class and implements several classes or interfaces. This means the class will inherit several types at the same time, and can be treated as such. For example :

    class D extends A, implements B, implements C {
    }

Every instance of D will have the type D but you will also be able to use it where an instance of type A, B or C is required. This means that every instance of D also has the types A , B and C.

Extends

When extending a class, your class inherits from all public and private non-static fields. You can then use them in your class as if they where declared here. You can also override a method by redefining it with the same number of arguments and types as its superclass. Your class can not inherit static fields.

When a method is overridden, then you can still access the superclass method using super :

    class B extends A {
        override function foo() : Int {
            return super.foo() + 1;
        }
    }

In your class constructor you can call the superclass constructor using also super :

    class B extends A {
        function new() {
            super(36,"");
        }
    }

Implements

When implementing a class or an interface, your class is required to implement all the fields declared or inherited by the class it implements, with the same type and name. However the field might already be inherited from a superclass.

Interfaces

An Interface is an abstract type. It is declared using the interface keyword. By default, all interface fields are public. Interfaces cannot be instantiated.

    interface PointProto {
        var x : Int;
        var y : Int;
        function length() : Int;
    }

An interface can also implement one or several interfaces :

    interface PointMore implements PointProto {
        function distanceTo( p : PointProto ) : Float;
    } 

Helper Classes


In haXe, it is possible to have more than one class definition per class file:
// both definitions in Foo.hx
class Foo { ... }
class FooHelper { ... }

This is fairly common in many object oriented languages such as Java. However, unlike other such languages, haXe also allows for these internal helper classes to be publicly available outside of the main class. By importing the main class, the helper class becomes available:

// in Bar.hx
import Foo;
class Bar{
     var b:FooHelper;
}

The helper class can also be made accessible via an extended package declaration:

// in Bar.hx
class Bar{
     var b:Foo.FooHelper;
}

The use of public internal helper classes is typically not a recommended practice in most languages. Since helper class names do not correspond with their .hx file names, they can be harder to find in source trees.

HaXe lets you mark an internal helper class with the private keyword, in the same way that fields are marked:

// both definitions in Foo.hx
class Foo { ... }
private class FooHelper { ... }

This prevents the internal helper class from being accessed outside of the main class.

Unless there is a good reason for their use, consider placing each public class definition in its own .hx file, or make the internal class private, to prevent its definitions being included (and possibly causing a name conflict) when the main class is imported.

«« Type Inference - Type Parameters »»

version #8835, modified 2010-06-16 21:52:36 by jpsecher