How to use Polymorphism in OpenFL / Haxe

@singmajesty

Hi

I am struggling with polymorphism to be used in OpenFL / Haxe with no success.
Well here’s what I want

Let’s say I have 3 classes each have one common method with different implementations

Class A {
function doSomething():Void
{
trace(“Do Something A”);
}
}

Class B {
function doSomething():Void
{
trace(“Do Something B”);
}
}

Class C {
function doSomething():Void
{
trace(“Do Something C”);
}
}

Here’s some code in other class

var className:String = “C”
var polyClass = Type.resolveClass(className)
polyClass.doSomething() // THROWS ERROR

Basically what i want is the polyClass should execute the doSomething method of the respective classes (Class C in this case). If I change the className then the doSomething method of that class should execute.

Is the above approach correct or is there any other way to achieve polymorphic behavior ?
Please Help

Is this not usable in your design approach ?
I guess you can’t succeed polymorphism without unification, so your goal may be to succeed unification of your different classes.

Or with Type parameters Class<Type> to avoid use of casts ?

I have used cast but failed.

I had extended Class A, Class B and Class C with a common class (lets say Class Z).
Here’s the updated code but failed

var className:String = “C”
var polyClass:ClassZ = cast(Type.resolveClass(className), ClassZ) // GETTING CAST ERROR
polyClass.doSomething()

You should probably use interfaces.

Make a new Interface class with doSomething() method then use that interface in all A,B,C classes.

interface MyInterface {
	public function doSomething():Void;
}

class A implements MyInterface {
	public function doSomething():Void {
		trace("class A");
	}
}

class B implements MyInterface {
	public function doSomething():Void {
		trace("class B");
	}
}

var className = "B";
var polyClass = Type.createInstance(Type.resolveClass(className), []);
cast(polyClass, MyInterface).doSomething();

resolveClass() takes the full path (packages included) of the class you need
createInstance() takes as the second argument an array of values that are applied to the constructor. Those values must be in the exact number and must be passed even if they are optional (nulls are good in that case).

Thanks @guruas3

It worked. But there is a small glitch.
I don’t want Type.createInstance since I have already instantiated a symbol.

For eg : var b:B = new B();

So how do I omit Type.createInstance.
I tried this

var className = “B”;
var polyClass = Type.resolveClass(className); // Reference to already instantiated B
cast(polyClass, MyInterface).doSomething(); // But Casting fails due to omission of Type.createInstance

You sure you need Type.resolveClass? How many classes do you have? Maybe it’s easier to create a function that has a switch inside and returns class based on className param

I have many classes … so I am avoiding the switch statement.
I am following the previous approach

var className = “B”;
var polyClass = Type.createInstance(Type.resolveClass(className), []);
cast(polyClass, MyInterface).doSomething();

But I don’t want Type.createInstance since I already have instances initiated.
Omitting the Type.createInstance results in errors as described before.

Instead of Type.createInstance, the Type.resolveClass should automatically resolve to a instance already initiated. For eg. If Type.resolveClass returns class B it should hook into the already initiated B class instance and I should be able to invoke methods on B thereafter.

Hope I am clear regarding my query…

Ok it’s clear but you can’t just grab already initiated class only by Type.resolveClass. Imagine having 3 instances of class B.

var b1:B = new B();
var b2:B = new B();
var b3:B = new B();

Type.resolveClass() can’t know which one of these you want to get.

So it would be better if you insert some of your code here and maybe we can come up with a solution.

may be you should look at Factory pattern