测试对象是否是 Google 闭包 class 框架中接口的实现

Test if object is implementation of interface in Google Closure class framework

如何测试 JavaScript 对象是否是使用 Google Closure inheritance mechanism 的接口的实现?


我在通过 new my.Dog() 创建的对象中找不到任何 my.Animal 的提示,并且 object instanceof my.Animal 无效。关于接口的唯一信息是忘记在子 class 中实现方法时出现编译器错误 class.

/**
 * @interface
 */
my.Animal = function() {};

/**
 * Does something.
 * @return {string}
 */
my.Animal.prototype.doSomething;

/**
 * @constructor
 * @implements {my.Animal}
 */
my.Dog = function() {};

/** @inheritDoc */
my.Dog.prototype.doSomething() = function {
    return "something";
}

var dog = new my.Dog();
console.log(dog instanceof my.Animal); // returns false

我发现的一种方法是大致测试接口的 属性,尽管这在很多方面都很糟糕:

console.log(!!dog.doSomething); // returns true

你不能直接。

在 Closure-compiler 类型系统中,@extends 用于继承并与 instanceof 测试相关。 @implements 表示的接口实现是严格的编译时检查。它们承诺您的对象包含与接口定义相匹配的方法和属性。

因此,要在运行时以全面的方式测试它们,您需要检查每个 属性 接口的存在和类型。

@interface 纯粹是一个类型检查器构造。在未编译的代码中,没有任何东西可以检查 @interface/@implements 的注释来为 运行 时间检查添加任何连接。 Closure 的目标是代码在编译前后将 运行 相同(假设您遵守所使用的优化模式的限制)。当需要 运行 时间检查时,典型的模式是标记 class 实现您感兴趣的接口:

my.Dog.prototype.implements_my_Animal = true;

然后

if (foo.implements_my_Animal) ...

这有点烦人,所以您不会在不需要的地方看到它。有多种方法可以包装它,但是,如果您使用 ADVANCED 模式,大多数会导致实现 class(在您的示例中为 my.Dog)转义并且如果未使用则不可移除。