我正在为Mapbox-gl-js的源对象构建Jsinteropted包装器。

我有一个抽象类Source,它嵌入了诸如获取/设置源类型的默认方法。

@JsType(isNative = true, namespace = GLOBAL, name = JS_OBJECT_NAME)
public class Source {

    @JsProperty
    protected final native String getType();

    @JsProperty
    protected final native void setType(String type);

}


而且我有一些继承的类,必须(根据Mapbbox文档)定义type属性!所以我想做些类似的事情:

@JsType(isNative = true, namespace = GLOBAL, name = JS_OBJECT_NAME)
public class GeoJsonSource extends Source {

    @JsConstructor
    public GeoJson() {
        setType("geojson");
    }

}


要么

@JsType(isNative = true, namespace = GLOBAL, name = JS_OBJECT_NAME)
public class GeoJsonSource extends Source {

    @JsProperty
    private String type = "geojson";

}


但是两者都被GWT编译器禁止。

现在,我使用一个创建GeoJsonSource的工厂,然后放置正确的type属性,但是我想知道是否有Jsinteropt方式​​可以做到这一点?

最佳答案

您如何在其他人的类型上设置默认值?你不知道

记住,您已经告诉编译器您只是在描述js类Object-如果有默认值,则它们已经存在。

考虑一下您将如何在JS中执行此操作-通常只需{type:"geojson"}var obj = {}; obj.type = "geojson";即可完成两个必需的步骤:a)创建一个普通对象,b)分配某种默认情况下必须存在的类型。

工厂可以工作,也许是GeoJsonSource中的静态方法,所以很清楚您要做什么。



另一个选择是不要将GeoJsonSource类型标记为native,并且不要在全局命名空间中为其指定对象名称(即,不允许您重写其他人的数据)(如果适合您的用例)。现在,这将允许您控制类-定义默认值,在构造函数中添加逻辑等,但是必须确保正确导出方法。

这种方法的局限性包括以下事实:从JSON字符串读取的任何对象都不是您的GeoJsonSource类型(但是另一方面,这可能并不重要,因为它可能已经具有type属性。逻辑仍然会丢失)但是,由于它的方法,因为从JSON读取总是创建普通的Object实例(除非您将reviver函数传递给JSON.parse())。

同样,从JS传递的普通对象或从JSON.parse()读取的普通对象将无法正确通过针对非本机类型的instanceof检查,这可能要求您在通常编写惯用Java的某些地方使用Js.uncheckedCast



由于您正在构建包装器(可能被其他人使用,他们可能不一定完全像您一样理解这些限制),所以我倾向于采用工厂方法-是的,它需要您做一些设置,但是在普通JS中,您的要求更加清楚,并且如果有人将普通JS对象视为Java GeoJsonSource(因为它是一个),则行为会更加可预测。

10-04 21:07
查看更多