0

我正在为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 方法可以做到这一点?

4

1 回答 1

2

您如何为其他人的类型设置默认值?你没有。

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

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

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


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

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

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


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

于 2018-08-30T12:41:00.637 回答