Bug with Dynamic type on HTML5 platorm

I think I’ve found a bug, try this:

private function center(object:Sprite):Void
{
	object.x = stage.stageWidth / 2 - object.width / 2;
	object.y = stage.stageHeight / 2 - object.height / 2;
}

It works in all platfroms, now change the type from Sprite to Dynamic, like this:

private function center(object:Dynamic):Void
{
	object.x = stage.stageWidth / 2 - object.width / 2;
	object.y = stage.stageHeight / 2 - object.height / 2;
}

Now the object is centered only in the Flash platform and not in HTML5. I don’t have time to test it on the other platforms.
This is normal or it’s a bug?

1 Like
public var x (get, set):Float;
public var y (get, set):Float;
public var width (get, set):Float;
public var height (get, set):Float;

See the pattern? None of those are physical fields.

I suspect that setting the type to Dynamic makes Haxe ignore the getters and setters. Instead of getting/setting the values you want, you’re trying to access variables that don’t exist.

Try this:

private function center(object:Dynamic):Void
{
	Reflect.setProperty(object, "x", stage.stageWidth / 2 - Reflect.getProperty(object, "width") / 2);
	Reflect.setProperty(object, "y", stage.stageHeight / 2 - Reflect.getProperty(object, "height") / 2);
}
1 Like

Your code works! but for me this is a bug since every lenguage feature should work in the same way in all the platforms.
Do you think this is a bug of the Haxe lenguage or OpenFL? I don’t know how OpenFL works intarnally. This can help me to report the problem in the right place.

This is the expected Haxe behavior

The Haxe C++ target actually used to work regardless, but I believe for Haxe 3.2 it was broken in order to behave in the same way as other platforms. You’ll need an interface or a set type in order to handle this without reflection

The code I quoted was from OpenFL, so if anything, it’s an OpenFL issue. But as Joshua said, the real problem is that you’re trying to use Dynamic rather than an interface, typedef, or the actual type.

Is there any reason you can’t just declare object as a DisplayObject?

The center function can work with a Rectangle as well, or any object containing x, y , width and height properties.
I think this should be fixed in OpenFL, because is affecting one platform and not the other.

This will affect anything but Flash Player, since Flash Player supports get/set properties, while JavaScript and Neko do not in all cases. C++ allows getters and setters (I believe), but I usually see separate get and set methods instead

Haxe can’t design around limitations in certain language targets, also, I believe the get_* set_* methods is faster, if not simpler. This is not an OpenFL issue, the only way around this would be to avoid getters and setters altogether, but this would not allow for overriding with a custom getter/setter, and would hurt the way the framework works :wink:

Thanks for the clarification. Now I understand
I hate using stuff like Dynamic and now that I have to use Reflection my code looks like crap, I can’t find another solution.
I often need to implement a function that can support different types, like in the example I posted.
In C# I would write it this way (function overloading):

public void align(Rect rectangle)
public void align(DisplayObject object)

This is the closest thing I can get in Haxe:

function align(?r:Rectangle, ?d:DisplayObject)

But you can provide both parameters at the same time and that is not the idea, can be confusing for someone implementing the method.

If Haxe adds multiple type parameters wold be great:

function align(object:(Rectangle,DisplayObject)){

}

Like this? http://try.haxe.org/#Aa970

1 Like

You can use different function names, obviously:

public function alignRect (rect:Rectangle):Void {}

public function align (object:DisplayObject):Void {}

Or I learned recently that Haxe supports skipping non-matching parameters, which is interesting:

public function align (rect:Rectangle = null, object:DisplayObject = null):Void {
    
    if (rect != null) {  } // align rect
    else if (object != null) { } // align object 
    
}

align (rect);
align (object);

When I look at methods like this, I don’t think of passing the second parameter type, and expecting it to skip the first, but if you’re strictly looking for typed method overloading (for stuff like this) and know what you’re doing, this can be a solution

Otherwise, another solution is using Std.is with casting, instead of reflection:

public function align (object:Dynamic):Void {
    
    if (Std.is (object, Rectangle)) {
        
        var rect:Rectangle = cast object;
        // align rect
        
    } else if (Std.is (object, DisplayObject)) {
        
        var displayObject:DisplayObject = cast object;
        // align object
        
    }
    
}

mrcdk solution looks good! thanks!. But not 100% perfect because it seems that I can’t add more than 2 types. Also it’s not part of the lenguage, looks like a hack, but I’ll use this solution.
The easy way is simply using different function names like singmajesty says. Not what I wanted but I’m going to do that when I need 3 or more types.

What part isn’t part of the language? I recommend you to read the Haxe manual http://haxe.org/manual/

Sorry, what I mean is that you implemented OneOf, if that were part of the language, we probably have better support to add more than 2 types and get the object with simple sintax. As part of the lenguage I mean an already made implementation.

abstract OneOf<A, B>(haxe.ds.Either<A, B>) to haxe.ds.Either<A, B> 
{
    inline function new(e) this = e;
    @:from static inline function fromA<A>(o:A) return new OneOf(Left(o));
    @:from static inline function fromB<B>(r:B) return new OneOf(Right(r));
}

What you did is great anyway.

Well, the abstract is just you you don’t have to manually call the function like align(Left(myDisplayObject)) or align(Right(myRectangle))

1 Like