是否有一个简单的轻量级/廉价调用来确定对象是否支持命名方法? 所以,在这个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异常,但我认为这是不好的做法且价格昂贵?
答案 0 :(得分:6)
简短的回答是'不'。 FrédéricHamidi提供的答案并不正确,但它在dart2js中不起作用(dart:镜子在dart2js中基本上没有实现)。
此外,在检查对象是否响应特定方法时,在其他语言(例如Ruby)中非常常见,但对我来说它似乎并不特别Dart-y。也许一旦Dart完全支持镜像,这将会改变。
很难说基于镜子的反射是否“轻巧/便宜”。这取决于用例以及如何定义这些术语。
我想说最好的办法是调用对象上的方法,捕获NoSuchMethod异常,并实现一些默认的错误处理行为。如果您通常希望该方法存在,这尤其有意义。
答案 1 :(得分: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
}
}
答案 2 :(得分: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);
}
答案 3 :(得分:1)
使用稍微不同的方法,我通过检查实例函数列表来检查给定方法是否存在:
InstanceMirror im = reflect(this);
Symbol fn = new Symbol('$functionName');
if (im.type.instanceMembers.keys.contains(fn)) {
im.invoke(fn, params);
}
答案 4 :(得分:0)
不是轻量级,但不需要mirrors
(并且在重新阅读已接受的答案后,它基本上是接受的答案暗示的可能性):
dynamic _toJson(dynamic obj) {
try {
return obj.toJson();
} catch(NoSuchMethodError) {
return obj;
}
}
我只是将它用于调试/故障排除目的 - 我从未将此代码投入生产。理想情况下,你最好定义某种界面并将其作为obj
而不是像@thetrompf建议的那样传递。
答案 5 :(得分:0)
这是一种解决方法,但是我使用了一个基本上是内联try catch的小助手:
String json = ifHasMethodElse(() => obj.toJson(), null)
dynamic ifHasMethodElse(Function closureWithCall, dynamic elseThis) {
try {
return closureWithCall();
} catch (NoSuchMethodError, e) {
return elseThis;
}
}