简体   繁体   English

如何将接口实现传递给Google Closure JavaScript库中的函数

[英]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依赖于Foothe_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: 综上所述,这两种方法都可以满足您的要求,但对于库用户来说意味着不同的事情:

  1. With the first approach, your user needs to provide a whole new type annotated with @implements . 使用第一种方法时,您的用户需要提供一种全新的类型,并带有@implements注释。
  2. With the second approach, your user may have to subclass 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.

相关问题 在Javascript / google关闭库中进行类型转换 - Typecasting in Javascript / google closure library 如何在Javascript接口中将Javascript函数作为参数传递? - How to pass a Javascript function as an argument in Javascript Interface? 测试对象是否是Google Closure类框架中的接口实现 - Test if object is implementation of interface in Google Closure class framework 如何将外部变量传递给私有javascript外部闭包函数? - How to pass external variables to a private javascript outer closure function? 使用Google Closure库解析正确的继承/子类实现 - Anatomy of a proper inheritance / subclass implementation using Google Closure Library JavaScript:更改库 function 的实现 - JavaScript: change implementation of library function 如何用闭包调用Javascript函数? - How to call a Javascript function with closure? 如何使用闭包创建一个javascript库 - How to create a javascript library using a closure 如何使用外部Javascript库(如jQuery)重命名Google Closure样式表? - How do I use Google Closure Stylesheet renaming with an external Javascript Library such as jQuery? 如何将代理对象作为上下文传递给javascript中的闭包 - How to pass a Proxy object as context to a closure in javascript
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM