Using type parameters to have a function return a sub-type

91 views
Skip to first unread message

David G

unread,
Mar 27, 2016, 9:30:14 PM3/27/16
to Haxe
Consider the following:

class Fruit {
    public function new() {
        
    }
}

class Apple extends Fruit {
    public var name = 'apple';
}
class Pear extends Fruit {
    public var name = 'pear';
}

class Test {
    static function main() {
        var fruits = new Array<Fruit>();
        
        fruits.push(new Apple());
        fruits.push(new Pear());

        trace(cast(fruits[0], Apple).name);
    }
}

I'm trying to figure out how to encapsulate the cast into a function.  That is, I have a list of a given type that is populated sub-types that I'd like to access from a single function.

To be clear, in my specific case, how the elements are found is not important.

I've given this a few swings, and the syntax just doesn't seem to be clicking since nothing seems to actually compile.  Any help would ]be appreciated.

Thanks!

David

Justin L Mills

unread,
Mar 27, 2016, 9:48:47 PM3/27/16
to haxe...@googlegroups.com
I am not completely sure what the aim is or if I have answered your
question but you can switch on the Type and you can use a soft cast due
to the inheritance.
http://try.thx-lib.org/#C34F4

Justin L Mills

unread,
Mar 27, 2016, 9:57:41 PM3/27/16
to haxe...@googlegroups.com
The Type.getClass looks quite heavy in js, there maybe lighter runtime
approaches than this kind of reflection but they probably involve macros
to do the work at compile and is only really worth looking into if it
seems a bottle neck.

David Granado

unread,
Mar 27, 2016, 10:40:32 PM3/27/16
to Haxe
Thanks for the suggestion, Justin!

I was hoping there might be some sort of type parameter method of doing this.  Being new, I'm not sure if this is the right tool for the job.

I've been living mostly in a javascript world for years now, so part of the goal is to kick the rust off the horribly atrophied strongly-typed part of my brain.  So, in theory, I could have dynamic return types and everything would probably work fine.

However, I'm wondering if there is a way to do this while still keeping the type system on.

In the end I'm hoping to get something as close as possible to C# to a generic return type in C# like this:

foo.getFruit<Apple>();

Is there something that accomplishes this in haxe?  There's a note about this in the "Triva" section on the Type Parameters page.  However, I'm not sure if this means that you can't use type parameters without having a value parameter to infer from.

Jonathan Ong

unread,
Mar 28, 2016, 12:32:38 AM3/28/16
to Haxe
I apologise if this doesn't match your use case, but are you not able to add methods to the base class and override them in the sub-classes?
Message has been deleted

Yoni Gueta

unread,
Mar 28, 2016, 5:31:52 AM3/28/16
to Haxe

well at least for class types you can simply do this:

Justin L Mills

unread,
Mar 28, 2016, 8:17:58 AM3/28/16
to haxe...@googlegroups.com
Ah 'is' but for JS target that seems to generate even more code than
getClass or atleast pretty much the same stuff, I think a switch with it
would be better and if you have to use using then do it on 'Std', the
'as' static just adds another function with little gain.

Benjamin Dubois

unread,
Mar 28, 2016, 8:45:47 AM3/28/16
to Haxe
From your example, I'll follow Jonathan advice :
Just put the name property in the Fruit classe, no more cast will be needed and for the methods you can override them in the subclass.

If you don't have code in the Fruit class maybe you should rather create an interface to ensure field are populated.

Of course you can mix inheritance and interface to fit you needs.

On Mon, Mar 28, 2016 at 2:17 PM, Justin L Mills <j...@justinfront.net> wrote:
Ah 'is' but for JS target that seems to generate even more code than getClass or atleast pretty much the same stuff, I think a switch with it would be better and if you have to use using then do it on 'Std', the 'as' static just adds another function with little gain.


--
To post to this group haxe...@googlegroups.com
http://groups.google.com/group/haxelang?hl=en
--- You received this message because you are subscribed to the Google Groups "Haxe" group.
For more options, visit https://groups.google.com/d/optout.

Itzik Arzoni

unread,
Mar 28, 2016, 10:54:29 AM3/28/16
to Haxe
I just wander why is this solution not a valid one?

Justin L Mills

unread,
Mar 28, 2016, 11:15:09 AM3/28/16
to haxe...@googlegroups.com
Yep I think it's a good one but I assumed the question was a cut down of a larger problem where such an approach was not acceptable, for instance if you wanted to check a different parameter depending on the fruit but where one parameter was not applicable to the other and so would be rather artificial to put in the parent class, I did not think of anything specific for fruit such as apple and pear but I expect there is some attribute that is only relevant to one of the fruits. 
Message has been deleted

David Granado

unread,
Mar 28, 2016, 11:49:08 AM3/28/16
to Haxe
Thanks, everyone, for all the feedback.  @JLM, you are correct, I did try and pare it down, but I think I may have over-simplified by trying to focus on the return type of a function.  Showing how I want to use it may help clarify.

Here is an example with a little more meat on it: http://try.haxe.org/#A0fAd

Jonathan Ong

unread,
Mar 28, 2016, 1:25:43 PM3/28/16
to Haxe
In that case, maybe Juraj/back2dos' macro-based entity (https://gist.github.com/back2dos/0f0bdf8fc114464ab329) could come in useful, as mentioned in the other thread about mapping classes to components (https://groups.google.com/forum/#!topic/haxelang/t1-2occ95VU).

I forked his GitHub gist and added your example: https://gist.github.com/jonongjs/133e5d99f3d3d47d4b44
Unfortunately, it seems that at this time, Try Haxe doesn't support macros, so I can't demo this code there :(

David Granado

unread,
Mar 28, 2016, 2:02:12 PM3/28/16
to Haxe
Thanks, Jonathan.  Looking at that "test" file, it looks like this is exactly what I'm looking for.

I saw that other post and to avoid duplication, I focused on the return type.  I figured I'd try and understand that answer and hook that up to whatever answer came out of this.  But since I didn't fully understand the answer, I didn't realize that the answer to this was also buried in there.

Since I understand about 3 characters in those add and get methods, it looks like I've got some studying and experimentation to do.  lol.

Thanks for the help, everyone!

Munir Hussin

unread,
Apr 20, 2016, 3:35:20 PM4/20/16
to Haxe


On Monday, March 28, 2016 at 10:40:32 AM UTC+8, David Granado wrote:

In the end I'm hoping to get something as close as possible to C# to a generic return type in C# like this:

foo.getFruit<Apple>();


This somewhat mimics C# generic return type like in your example.


class Fruit
{
    public function new()
    {
    }

    public function getFruit<T:Fruit>(cls:Class<T>):T
    {
        return Std.is(this, cls) ? cast this : throw 'Not a ${Type.getClassName(cls)}';
    }
}

var f:Fruit = new Apple();
trace(f.getFruit(Apple).name);

 Hope that helps.
Reply all
Reply to author
Forward
0 new messages