如何将接口实现传递到google closure javascript库中的函数
我想定义一个接口,让库用户实现,并确保在某些函数中,输入参数是给定接口的实现。怎么做 例如:如何将接口实现传递到google closure javascript库中的函数,javascript,google-closure-compiler,google-closure,google-closure-library,Javascript,Google Closure Compiler,Google Closure,Google Closure Library,我想定义一个接口,让库用户实现,并确保在某些函数中,输入参数是给定接口的实现。怎么做 例如: /** * @interface */ var FooInterface = function(){}; /** * nothing special */ FooInterface.prototype.bar = function(){}; /** * @constructor * @implements {FooInterface} */ var Foo = function() {
/**
* @interface
*/
var FooInterface = function(){};
/**
* nothing special
*/
FooInterface.prototype.bar = function(){};
/**
* @constructor
* @implements {FooInterface}
*/
var Foo = function() { /* hello world */ };
/**
* @override
*/
Foo.prototype.bar = function() { /* do something */ };
/**
* ?? How to annotate, that 'foo' is an implementation of FooInterface,
* but also instance of something else ??
* @function
* @param {FooInterface} foo
*/
var the_function = function(foo) {
// foo should be actually instance of Foo, but I want to make sure,
// it is an implementation of FooInterface
// how to indicate that?
foo.bar(); // code continues
}
编辑:提问者在另一个论坛扩展了他的问题,该论坛的讨论线索提供了更多的见解
为了确保您的库函数
,_函数
实现接口,但不希望包含可能实现接口的定义(将Foo
完全交给用户),您只需将参数收紧为不可为空的接口类型:
// ...snip: FooInterface declaration...
/**
* @param {!FooInterface} foo
*/
var the_function = function(foo) {
// non-nullable ensures that something like null.bar() is not invoked here.
foo.bar();
};
用户必须定义自己的FooInterface
实现,并将其作为foo
参数传递。如果他要通过FooInterface
,编译器将通过高级优化运行,检测到它不是构造函数(因为接口和构造函数是互斥的),并输出警告:
JSC_TYPE_MISMATCH: actual parameter 1 of the_function does not match formal parameter
found : function (this:FooInterface): ?
required: FooInterface at line ... character ...
因此,通过收紧接口参数类型,您的需求得到了满足:“参数既是接口的实现,也是其他对象的实例”
另一种方法是提供一种功能最低的实现,既可以在库代码中执行
函数
,又可以作为用户实现的蓝图。您可以通过在库代码中包含Foo
来实现这一点,并使函数的定义依赖于Foo
:
// ...snip: FooInterface declaration...
/**
* @constructor
* @implements {FooInterface}
*/
var Foo = function() {/* ... */};
/** @override */
Foo.prototype.bar = function() {/* ... */};
/** @param {!Foo} foo */
var the_function = function(foo) {
foo.bar();
};
在这种情况下,不需要使用任何引用FooInterface
的内容对_函数进行注释。编译器将要求完成上述接口检查。如果Foo
未能实现bar()
,它将输出警告:JSC\u接口\u方法\u未实现:接口Foo接口上的属性栏未通过第行的Foo类型实现。。。字符…
总之,这两种方法都满足了您的需求,但对您的库的用户来说意味着不同的东西:
对于第一种方法,用户需要提供一个全新的类型,并用@implements
注释
使用第二种方法,您的用户可能必须使用自己的实现对Foo
进行子类化。可能不需要引用接口。Foo
中列出的基本功能可以重用
如果您可以使用接口类型foointerace
作为注释类型(如您的示例中),我不确定它是否有效,那么您可以使用instanceof
在函数中测试对象的具体类型。见:
如前所述,我不确定是否可以使用接口类型作为带注释的参数类型。否则,您可能必须使用未知类型注释(?)并对对象进行duck测试。只需确保在以任何方式访问字段之前将其强制转换为接口类型,这样编译器就可以在高级编译模式下正确解析属性名
我会按照以下思路做一些事情:
/**
* @function
* @param {*} foo
*/
var the_function = function(foo) {
// foo can be any object, we just want to make sure,
// it is implementing of FooInterface
if (foo instanceof FooInterface) {
(/** @type{FooInterface}*/(foo)).bar();
}
};
FooInterface的foo实例总是错误的,因为FooInterface
从不在foo
的继承链中。接口是闭包中的编译时构造,最终被剥离,因此不适合运行时检查。