2016-08-05 203 views
2

修訂問題:鑄造一個泛型類型中HAXE

我已經做了一些挖掘和工作過勞倫斯·泰勒的回答。我幾乎在那裏,但它似乎不能與遞歸包裝。這裏有一個更新的可運行的代碼片段,它顯示了問題(這次使用我的類,因爲我不想重新定義一切)

New runnable code sample

具體地,請注意,{t : 3}(正確地)結合到一個公平的第一時間,但同時{t : {t : 3}}(也正確地)結合到一個公平,嵌套{t : 3}結合到nonequitable。這怎麼可能是相同的對象t1t2首次結合Equitable,但NonEquitable第二次?


問題V1:

我隆隆通過HAXE並已達到簡化爲這一點:

interface SelfReferringInterface<X> { 
    public function doStuff(x : X) : Void; 
} 

class A { 
    private var x : Int; 
    public function new(x : Int){this.x = x;} 

    public function toString() {return Std.string(x);} 
} 

class B implements SelfReferringInterface<B> { 
    private var x : Int; 

    public function new (x : Int){this.x = x;} 

    public function doStuff(b : B) { 
     trace(this + " and " + b); 
    } 

    public function toString() { return Std.string(x);} 
} 

從本質上講,我有一堆類(其中AB只是兩個),其中一些落實自己SelfReferringInterface(如B一樣),和其他人沒有實現它。

然後,我有一個通用類,它可以包含任何類型:

class GenericClass<T> { 
    private var t : T; 
    public function new(t : T) {this.t = t;} 
} 

我想一個方法添加到GenericClass<T>,如果它的TSelfReferringInterface的實施將調用doStuff,否則有一些其他默認行爲:

class GenericClass<T> { 
    private var t : T; 
    public function new(t : T) {this.t = t;} 

    public function doStuffOrTrace(t2 : T) { 
     //if t instanceof SelfReferringClass, call t.doStuff(t2) 
     //otherwise call trace(t) and ignore t2 
    } 
} 

這樣下面的測試方法可以做到以下幾點。

class Test { 
    static function main() { 
     new GenericClass<A>(new A(3)).doStuffOrTrace(new A(4));//Expect 3 
     new GenericClass<B>(new B(1)).doStuffOrTrace(new B(2));//Expect 1 and 2 
    } 
} 

是否正在執行doStuffOrTrace(..)在所有可能的?我可以控制所有的課程,但我試圖避免改變AB以使其成爲可能。必要時我可以添加到SelfReferringInterfaceGenericClass。想法?


我已經做了一些挖掘,它似乎(由於協方差useages),我寧願SelfReferringInterface<X>的typedef而非接口。我仍然堅持實施doStuffOrTrace(..),但也許這會打開新的途徑?

+0

我想嘗試的一件事是明確輸入包裝的輸出,對泛型類型的類型解析有一些含糊之處。 因爲應該隱式調用抽象構造函數,所以你不應該首先明確地調用wrap,並且可以完全避免Equatable的問題。 –

回答

4

最佳寫具有這兩種情況下的枚舉,包裹在一個抽象的及寫入@:從功能每種情況下,和使用,作爲輸入到doStuffOrTrace。

在正常使用時,調用該函數將導致正確的抽象構造函數的調用,然後你可以使用一個開關內部分化。

*編輯

@:from static public function fromHasInterface<T>(v:SelfReferringInterface<T>):HasInterfaceOrNot<T>{ 
    return THasInterface(v); 
} 
enum HasInterfaceOrNotT<T>{ 
    THasInterface(v:SelfReferringInterface<T>); 
    THasNotInterface(v:Dynamic); 
} 

看到正在運行的代碼here

+0

我可以給一個鏡頭..你可以添加一個有效使用@:從語法的例子嗎?這對我來說是新的 – Mshnik

+0

修正了與可運行代碼鏈接的答案。 –

+0

非常感謝!我使用你的代碼工作了90%,但我在遞歸調用中遇到了一些麻煩。看到我更新的問題 – Mshnik

1

你可以使用Std.is確定T的類型和其轉換成SelfReferringInterface實施doStuffOrTrace:

public function doStuffOrTrace(t2 : T) { 
    if(Std.is(t, SelfReferringInterface)){ 
     var castedT = cast(t, SelfReferringInterface<Dynamic>); 
     castedT.doStuff(t2); 
    }else{ 
     trace(t); 
    } 
} 

的問題是你從不明確地使用toString方法,所以它會被編譯器(dce)去掉,trace(t)會輸出'[object]'

您可以防止通過添加@:保留元數據的方法,但由於 不能修改A和B,你可以用-dce no-dce std編譯器標誌

這裏禁用DCE是try.haxe片段: http://try.haxe.org/#40402