In Haxe, how to enforce method declarations in subclass when it is not defined in it's "abstract" superclass?

511 Views Asked by At

I'm trying to write a class-definition in such a way that, when used within a function or var declaration (such as function instantiateMain(mainCls:Class<MyAbstractClass>)), it should enforce the subclass to have the required method(s) specification. For example, an init() method.

So...

Is there a way to write a class in an abstract way, so that it checks at compile-time for its subclass (the one calling ... extends MyAbstractClass) to declare a specific method(s), and YET be able to extend another existing class (ex: AbstractSprite extends Sprite, or AbstractMC extends MovieClip)?

Alternatively, can Class<...> list more than one constraint types (classes & interfaces)?

For example, Class<Sprite, MyInterface> - tried this already though, maybe my syntax is incorrect.

EDIT:

To add more of a context to the question, here's the code I'm trying to get working:

package;

import flash.display.DisplayObject;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.display.Stage;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.Lib;

class MyInitializer {
    public static var INSTANCE:MyInitializer;
    public static var STAGE:Stage;

    public static function init(clazz:Class<DisplayObject, InterfaceMain>) {
        if (INSTANCE != null) return INSTANCE;

        //Create a new instance of this global class:
        INSTANCE = new MyInitializer();

        //Add the 'Main' class to the stage:
        STAGE.addChild( Type.createInstance( clazz, [] ) );

        return INSTANCE;
    }
}

class SpriteMain extends Sprite implements InterfaceMain {

}

class MovieClipMain extends MovieClip implements InterfaceMain {

}

interface InterfaceMain {
    function init():Void;
}
2

There are 2 best solutions below

2
On BEST ANSWER

You can define types as having multiple constraints:

typedef Measurable = {
  public var length(default, null):Int;
}

class Constraints {
  static public function main() {
    trace(test([]));
    trace(test(["bar", "foo"]));
    // String should be Iterable<String>
    //test("foo");
  }

  static function
  test<T:(Iterable<String>, Measurable)>(a:T) {
    if (a.length == 0) return "empty";
    return a.iterator().next();
  }
}
0
On

You can use a base class that implements the interface and subclasses must override the methods implementation, i have ran into this problem myself a couple of times and there is no perfect solution.

You can also throw exceptions in the methods of the base class to enforce that the subclasses need to override them.