0

I need a generic based class that should work only for two primitive type. those types are not relevant to each other ( Not Implemented Not Extended each Other). is there any way?

J.J
  • 46
  • 6
  • Which version of haxe? Latest versions allows experimental Java support. – Unihedron Jul 23 '14 at 14:11
  • If there is no relationship between these types, then their intersection is empty, no? What is the point of such a restriction? Can you share some code to clarify? – back2dos Jul 23 '14 at 17:54

2 Answers2

0

Agreeing with other comments and answers, without knowing what you're trying to achieve it's hard to know what the point is of accepting two unrelated types.

A couple of things I can think of:

1. If you never use the objects in a type specific way (for example, you only ever serialize it to JSON, which would work for any type) then you can use an abstract wrapping dynamic:

As an example, take a look at this Either class from Andy Li's jQuery externs:

abstract Either<T1, T2>(Dynamic) from T1 from T2 to T1 to T2 {}

You could then call:

var arr:Array<Either<String,Int>>;
arr.push(0);
arr.push("hi");
var myInt = arr[0];
var myString:String = arr[1]; // you might need to use explicit type hints

This is basically an Array underneath the scenes, but it will only let you use a String or an Int.

2. If you're building you're own class, and just need to accept arguments of one type or another, you can just use optional function parameters:

function doSomething( ?myInt:Int, ?myString:String ) {
    if ( myInt!=null ) trace('Int!');
    else if ( myString!=null ) trace('String!');
}

3. If you want something like 1, but with stricter typing, you can use a more advanced abstract. At the risk of self promotion I wrote a blog post on this technique in detail, but I've pasted the basic code here:

class Test {
    static function main(){
        stringOrInt( "hello" );
        stringOrInt( 10 );
    }
    static function stringOrInt( either:AcceptEither<String,Int> ) {
        switch either.type {
            case Left(str): trace("string: "+str);
            case Right(int): trace("int: "+int);
        }
    }
}

abstract AcceptEither<A,B> (Either<A,B>) {
    public inline function new( e:Either<A,B> ) this = e;
    public var value(get,never):Dynamic;
    public var type(get,never):Either<A,B>;

    inline function get_value() switch this { case Left(v) | Right(v): return v; }
    @:to inline function get_type() return this;
    @:from static function fromA( v:A ):AcceptEither<A,B> return new AcceptEither( Left(v) );
    @:from static function fromB( v:B ):AcceptEither<A,B> return new AcceptEither( Right(v) );
}

enum Either<A,B> {
    Left( v:A );
    Right( v:B );
}

You could use this like var arr:Array<AcceptEither<String,Int>> = [] with any generic class.

Jason O'Neil
  • 5,908
  • 2
  • 27
  • 26
  • Thank you so much, i want to have a class (container for example) when we are instancing it should accept one of the two type (int or float). when i defined it int, it can not accept float and vice versa; i think eitherClass is not good idea. – J.J Jul 25 '14 at 11:43
  • @J.J then you should use the map approach I linked in the neighbour answer. Ask if you aren't getting how is it working(it's a bit cryptic if you aren't experienced with haxe). – stroncium Jul 27 '14 at 05:46
0

You might use the approach used in Map(haxe std lib). Here is the current source.

stroncium
  • 1,430
  • 9
  • 8