2017-03-29 1 views
1

Est-il possible d'avoir une contrainte sur les champs statiques dans Haxe? Par exemple nous pouvons avoir des classes qui ont un champ statique instance de type de classe correspondante. Et nous pouvons vouloir une fonction qui retournera une instance de classe passée en paramètre. Ceci est ma tentative:contrainte sur les champs statiques et l'inférence de type

class Foo { 
    static public var instance = new Foo(); 
    function new() {} 
} 

class Test { 
    // get instance from every class that have static field instance 
    static function getInstance<T, ClassT:({instance:T}, Class<T>)>(t:ClassT):T { 
     return t.instance; 
    } 

    static function main() { 
     var a = getInstance(Foo); 
     $type(a); //Test.hx:14: characters 14-15 : Warning : Unknown<0> 
    } 
} 

mais il échoue, car type parameter constraints are checked lazily. Des idées sur comment faire cela?

Répondre

1

Si vous ne me dérange pas en utilisant la macro, voici une solution: http://try-haxe.mrcdk.com/#7d650

Foo.hx

class Foo { 
    static public var instance = new Foo(); 
    public var foo:Int; 
    function new() {} 
} 

class Test { 

    macro static function getInstance(e) return Macro.getInstance(e); 

    static function _getInstance<T, ClassT:({instance:T}, Class<T>)>(t:ClassT):T 
     return t.instance; 

    static function main() { 
     var a = getInstance(Foo); 
     $type(a); 
    } 
} 

Macro.hx

import haxe.macro.Expr; 
import haxe.macro.Context.*; 
using tink.MacroApi; 

class Macro { 
    public static function getInstance(e:Expr) { 
     var ct = TPath(e.toString().asTypePath()); 
     return macro (Test._getInstance($e):$ct); 
    } 
} 
+0

est-il pas plus facile faire comme ça, si vous utilisez macro: 'fonction macro statique getInstance (e: exprof >): exprof return macro $ e.instance; ' – romamik

+0

Bien sûr, j'essaie simplement de ne pas tout déplacer en macro, donc vous pouvez étendre la fonction, si nécessaire, sans entrer dans le code de macro. – KevinResoL

+0

C'est un bon point – romamik

2

Avez-vous pensé à utiliser un typedef?

Heres une édition rapide de votre code montrant l'idée de base

typedef HasInstance = { 
    var instance:Dynamic; 
} 

class Foo { 
    static public var instance = new Foo(); 
    function new() {} 
} 

class Bar { 
    static public var instance = new Bar(); 
    function new() {} 
} 

class Test { 
    // get instance from every class that have static field instance 
    static function getInstance<T:HasInstance>(t:T):T { 
     trace(t); 
     return t.instance; 
    } 

    static function main() { 
     var a = getInstance(Foo); 
     trace(a); 
     $type(a); 
     var b = getInstance(Bar); 
     trace(b); 
     $type(b); 
    } 
} 

exemple sur try haxe!

vous changeriez le type d'instance dans le typedef être plus adapté à vos besoins, et vous pouvez également limiter typedefs aussi, ce qui peut être très utile

+0

Cela ne fonctionne tout simplement pas. Dans votre exemple 'a' est de type' Class 'mais la valeur réelle de' a' est de type 'Foo'. Cela se terminera par des erreurs d'exécution. – romamik

+1

C'est la meilleure solution, mais vous pouvez utiliser un générique au lieu de Dynamic. http://try.haxe.org/#6cc96 – kobi7

+0

Oups idiot moi, merci pour la correction! – ediblebird