Casting with generic collections?

68 views
Skip to first unread message

Lea Hayes

unread,
Aug 21, 2013, 12:13:45 AM8/21/13
to haxe...@googlegroups.com
Hey guys

What is the correct way to achieve the following?

class MyBaseClass { ... }

class A extends MyBaseClass { ... }

class B extends MyBaseClass { ... }

var collection = new Vector<A>(2);
collection
[0] = new A();
collection
[1] = new A();

function doSomethingGeneric(collection:Vector<MyBaseClass>) { ... }

// The following would work in C#
// but does not compile with Haxe
doSomethingGeneric
(collection);

Would this be properly addressed with the following?

doSomethingGeneric(cast(collection, Vector<MyBaseClass>));

Or is there a better approach?

Cheers!

dlots

unread,
Aug 21, 2013, 12:59:47 AM8/21/13
to haxe...@googlegroups.com
@:generic doSomethingGeneric<T:MyBaseClass>(collection:Vector<T>)

In addition, you ought to understand that @:generic programming is entirely necessary across the entire scope of parameterization when it comes to static targets (and the fact that you cannot parameterize a @:generic declaration with Dynamic). Without @:generic, everything turns into a Dynamic, with reflection being executed against a string switch statement. @:generic is of course optional.

Why are you using Vector?

Lea Hayes

unread,
Aug 21, 2013, 1:18:26 AM8/21/13
to haxe...@googlegroups.com
@:generic doSomethingGeneric<T:MyBaseClass>(collection:Vector<T>)

Thanks, I will give that a try!

Without @:generic, everything turns into a Dynamic, with reflection being executed against a string switch statement. @:generic is of course optional.

So performance-wise it's better to decorate with @:generic?

Why are you using Vector?

Reason 1: Because my arrays contain a fixed number of items (which doesn't change).
Reason 2: Vector's are supposed to perform better than List's on certain Haxe targets.

Given that my game by its very nature incurs a lot of loop iterations, it is important to maximise performance wherever possible. I am even considering swapping out my 'for in' loops with 'while' loops since this will avoid the instantiation of iterators. I really miss the syntax of traditional 'for(;;)' loops :(

dlots

unread,
Aug 21, 2013, 1:54:33 AM8/21/13
to haxe...@googlegroups.com
I'd recommend you benchmark array, list and vector and caxe's datastructures (if you really care all that much) for your targets. I'm not sure that is entirely correct. I personally use Array for everything.

Luca

unread,
Aug 21, 2013, 4:21:18 AM8/21/13
to haxe...@googlegroups.com
That this would work in c# means it automatically prevents you from adding elements to the collection, or that it is doing something it shouldn't be, or it doesn't care :P

The reason it doesn't compile in haxe is if it 'did' you would be allowed to do:

var x:Vector<A> = ...;
var y:Vector<MyBaseClass> = x;
y.push(new B()); // fine, B extends MyBaseClass.

But of course, that last line is completely wrong, y 'actually' points to a Vector<A> and it is 'not okay' to add a B to it.

The only way to correctly do this, is to provide an immutable reference to the Vector<A> (Similar to how Iterator works in Haxe already) and infact, you can use Iteratable for this already if you're using Array instead of Vector.

function f(xs:Iterable<MyBaseClass>) { }
var x:Array<A> = ...;
f(x); // compiles just fine.

It won't work for Vector, at least not at present as the abstract doesn't expose an iterator (Iterable<T> is defined as { iterator : Void -> Iterator<T> }, Iterator<T> as { next : Void -> T, hasNext : Void -> Bool }) 

TopHattedCoder

unread,
Aug 21, 2013, 12:01:18 PM8/21/13
to haxe...@googlegroups.com
Last time I checked, Vectors are much faster on system targets, and arrays are too when implemented as an ArrayDeque.

Lea Hayes

unread,
Aug 21, 2013, 6:58:36 PM8/21/13
to haxe...@googlegroups.com

@:generic doSomethingGeneric<T:MyBaseClass>(collection:Vector<T>)

This seems to be working fine!

I am still unsure as to what the @:generic meta data actually does though. I will examine the generated C++ source to see what the difference is with and without.

Thanks :)

Luca

unread,
Aug 21, 2013, 7:29:34 PM8/21/13
to haxe...@googlegroups.com
That code works because for every different T, you have a different implementation of the function.

Esssentially, it is the same thing as doing:

function doSomething_A(collection:Vector<A>) {}
function doSoemthing_B(collection:Vector<B>) {}
...
function doSomething_F(collection:Vector<F>) {}

you do not really need @;generic here though,
Reply all
Reply to author
Forward
0 new messages