Test if object is implementation of interface in G

2019-04-29 09:13发布

How can I test if an JavaScript object is an implementation of an interface using the Google Closure inheritance mechanism?


I could not find any hint of my.Animal in the objects created via new my.Dog() and object instanceof my.Animal didn't work. The only information about the interface are compiler errors when forgetting to implement methods in the child 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

One way I found is to approximately test for the property of the interfaces, though that's bad in so many aspects:

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

2条回答
\"骚年 ilove
2楼-- · 2019-04-29 09:48

You can't directly.

In the Closure-compiler type system, @extends is used for inheritance and correlates to instanceof tests. Interface implementations denoted by @implements are strictly a compile time check. They are a promise that your object contains methods and properties that match the definitions of the interface.

As such, to test for them at runtime in a comprehensive fashion, you would need to check for the existance and type of each property of the interface.

查看更多
爷的心禁止访问
3楼-- · 2019-04-29 09:53

@interface is purely a type checker construct. In uncompiled code there is nothing that can inspect the comments for @interface/@implements to add any wiring for runtime checks. The goal for Closure is that the code will run the same before and after compilation (assuming that you observe the restriction for the optimization mode you are using). The typical pattern when a runtime check is desired is to tag class that implements the interface you are interested in:

my.Dog.prototype.implements_my_Animal = true;

then

if (foo.implements_my_Animal) ...

This is a bit annoying so you don't see it where it isn't needed. There are various ways to wrap this but, if you use ADVANCED mode, most result in the implementing class (my.Dog in your example) escaping and not being removable if unused.

查看更多
登录 后发表回答