2013-04-05 26 views
2

是否有一個簡單的,輕量級/便宜的調用來確定一個對象是否支持命名方法? 因此,在這個obj.respondsTo會很好。調用一個方法,如果它存在

dynamic _toJson(dynamic obj) { 
    return obj.respondsTo('toJson'))? obj.toJson() : obj; 
} 

class Foo { 
    String foo = "Foo.foo"; 
    Bar bar = new Bar(); 
    Map toJson() { 
    return { 
     "foo" : _toJson(foo), 
     "bar" : _toJson(bar) 
    }; 
    } 
} 

一種選擇將只是把它和趕上noSuchMethod例外,但我想這是不好的做法和昂貴?

回答

5

簡短的回答是, '不'。 FrédéricHamidi提供的答案並不正確,但它在dart2js中不起作用(dart:鏡子在dart2js中基本未實現)。

另外,在檢查某個對象是否響應某個特定方法時,在其他語言(例如Ruby)中非常常見,但對我來說它並不是特別的Dart-y。也許一旦Dart完全支持鏡像,這將會改變。

很難說基於鏡子的反射是「輕便/便宜」。這取決於用例以及如何定義這些術語。

我會說你最好的選擇是調用對象的方法,捕獲NoSuchMethod異常,並實現一些默認的錯誤處理行爲。如果您通常期望該方法存在,這尤其有意義。

1

隨着dart:mirrors,你應該能夠寫類似:

bool respondsTo(dynamic obj, String methodName) 
{ 
    var mirror = reflect(obj); 
    return mirror.type.methods.values.map((MethodMirror method) => method.simpleName) 
            .contains(methodName); 
} 
2

如果對象是接口類型,則可以使用抽象方法定義接口/抽象類,然後調用您現在知道存在的方法。

abstract class JsonEncodable { 
    Map toJSON(); 
} 

Object _toJson(Object obj) { 
    return (obj is JsonEncodable)? obj.toJson() : obj; 
} 

class Foo implements JsonEncodable { 
    Map toJSON() { 
     // toJSON implementation 
    } 
} 
1

使用略有不同的方法,我檢查,如果通過檢查的實例函數的列表中存在給定的方法:

InstanceMirror im = reflect(this); 
Symbol fn = new Symbol('$functionName'); 
if (im.type.instanceMembers.keys.contains(fn)) { 
    im.invoke(fn, params); 
} 
0

不是輕量級的,但不要求mirrors(和在重讀所接受的答案之後,它基本上被接受的答案暗示爲可能性):

dynamic _toJson(dynamic obj) { 
    try { 
    return obj.toJson(); 
    } catch(NoSuchMethodError) { 
    return obj; 
    } 
} 

我已經使用這僅用於調試/故障排除的目的 - 我從來沒有把這個代碼投入生產。理想情況下,您最好定義某種界面並將其作爲您的obj而不是像@thetrompf所建議的那樣充當動態。

相關問題