[英]How to pass interface implementation to function in google closure javascript library
I would like to define an interface and let the implementation on the library user, and make sure, that in some function, the input parameter is an implementation of the given interface. 我想定义一个接口,并让该库用户实现该实现,并确保在某些函数中,输入参数是给定接口的实现。 How to do that? 怎么做?
Example: 例:
/**
* @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
}
EDIT: The asker expanded his question in another forum, whose discussion thread provides additional insights. 编辑:询问者在另一个论坛上扩大了他的问题,其讨论线程提供了更多的见解。
https://groups.google.com/forum/#!topic/closure-library-discuss/fF1epI9BPyA https://groups.google.com/forum/#!topic/closure-library-discuss/fF1epI9BPyA
To ensure your library function the_function
takes the implementation of an interface, but do not wish to include the definition of what could possibly implement it (leave Foo
completely in the hands of the user), you can simply tighten the parameter to a non-nullable interface type: 为了确保您的库函数the_function
采用接口的实现,但不希望包括可能实现该接口的定义(将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();
};
The user will have to define his own implementation of FooInterface
, and pass it as the foo
parameter. 用户将必须定义自己的FooInterface
实现,并将其作为foo
参数传递。 If he were to pass FooInterface
the compiler, running with advanced optimizations, will detect it is not a constructor (as interfaces and constructors are mutually exclusive) and output the warning: 如果他要通过FooInterface
,则使用高级优化运行的编译器将检测到它不是构造函数(因为接口和构造函数是互斥的),并输出警告:
JSC_TYPE_MISMATCH: actual parameter 1 of the_function does not match formal parameter
found : function (this:FooInterface): ?
required: FooInterface at line ... character ...
So, by tightening the interface parameter type your requirement is met: "parameter is both an implementation of an interface and instance of something else". 因此,通过加强接口参数类型,可以满足您的要求:“参数既是接口的实现又是其他东西的实例”。
Another approach is to provide a minimally functional implementation that can both fulfill the execution of the_function
within your library code, and serve as the blueprint of the user's implementation. 另一种方法是提供一种功能最少的实现,该实现既可以完成您的库代码中the_function
的执行,又可以充当用户实现的蓝图。 You can do this by including Foo
in your library code and make the definition of the_function
reliant on Foo
: 您可以通过在库代码中包含Foo
the_function
依赖于Foo
的the_function
的定义来the_function
:
// ...snip: FooInterface declaration...
/**
* @constructor
* @implements {FooInterface}
*/
var Foo = function() {/* ... */};
/** @override */
Foo.prototype.bar = function() {/* ... */};
/** @param {!Foo} foo */
var the_function = function(foo) {
foo.bar();
};
In this case, the_function
need not be annotated with anything referencing FooInterface
. 在这种情况下, the_function
不需要使用任何引用FooInterface
注释。 The compiler will have required that the above interface check is fulfilled. 编译器将要求完成上述接口检查。 If Foo
fails to implement bar()
, it will output the warning: JSC_INTERFACE_METHOD_NOT_IMPLEMENTED: property bar on interface FooInterface is not implemented by type Foo at line ... character ...
. 如果Foo
无法实现bar()
,它将输出警告: JSC_INTERFACE_METHOD_NOT_IMPLEMENTED: property bar on interface FooInterface is not implemented by type Foo at line ... character ...
。
To sum it up, both approaches fulfill your requirement, but mean different things to the user of your library: 综上所述,这两种方法都可以满足您的要求,但对于库用户来说意味着不同的事情:
@implements
. 使用第一种方法时,您的用户需要提供一种全新的类型,并带有@implements
注释。 Foo
with his own implementation. 使用第二种方法,您的用户可能必须用自己的实现来继承Foo
子类。 Referencing the interface may not be needed. 可能不需要引用该接口。 Basic functionality laid out in Foo
could be reused. Foo
列出的基本功能可以重复使用。 If you can just use the interface type FooInterface
as the annotated type (as in your example), which I'm not sure is valid, then you can test the object for the concrete type within the_function using instanceof
. 如果您可以仅使用接口类型FooInterface
作为带注释的类型(如您的示例中所示)(我不确定该类型是有效的),则可以使用instanceof
在the_function中测试对象的具体类型。 See: https://groups.google.com/forum/m/#!topic/closure-library-discuss/AphCYwDbI7w 请参阅: https : //groups.google.com/forum/m/#!topic / closure-library-discuss / AphCYwDbI7w
As I said before, I am not sure if you can use interface types as the annotated param type. 如前所述,我不确定是否可以将接口类型用作带注释的参数类型。 If not, you will probably have to use the unknown type annotation (?) and duck-test the object. 如果没有,您可能必须使用未知类型注释(?)并对该对象进行鸭子测试。 Just make sure you cast it to the interface type before accessing fields in any way, so the compiler can properly resolve property names in Advanced Compilation mode. 只需确保在以任何方式访问字段之前将其转换为接口类型,即可使编译器可以在“高级编译”模式下正确解析属性名称。
I'd do something along these lines: 我会按照以下方式做一些事情:
/**
* @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();
}
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.