【问题标题】:Are Interfaces in JavaScript necessary?JavaScript 中的接口是必需的吗?
【发布时间】:2023-04-08 15:14:01
【问题描述】:

我想这可能适用于任何动态语言,但我使用的是 JavaScript。我们有一种情况,我们正在用 JavaScript 编写几个控件,这些控件需要公开一个 Send() 函数,然后由托管 JavaScript 的页面调用该函数。我们有一个定义了这个 Send 函数的对象数组,因此我们遍历集合并在每个对象上调用 Send()。

在 OO 语言中,如果您想做类似的事情,您将拥有一个 IControl 接口,该接口具有必须由每个控件实现的 Send() 函数,然后您将拥有一组 IControl 实现'd 遍历并调用 send 方法。

我的问题是,由于 JavaScript 是一种动态语言,是否需要定义控件应继承的接口,或者仅调用控件上公开的 Send() 函数是否足够好?

【问题讨论】:

    标签: javascript oop interface dynamic-languages


    【解决方案1】:

    动态语言通常鼓励Duck Typing,其中对象的方法决定了它应该如何使用,而不是明确的契约(例如接口)。

    【讨论】:

    • 我不认为接口与鸭式打字相反。其实恰恰相反。通过声明接口,您可以清楚地说明您将尝试调用哪些方法。我经常发现接受类似文件的对象的方法,但没有明确指示类似文件的对象应该实现什么。 read() 和 close() 足够了吗?我还需要 seek() 吗?写()呢?接口是表达您的需求的一种清晰明确的方式,因此是一个很大的增强尤其是如果您想依赖鸭子打字
    • 即使具有简单地声明参数应具有的方法和成员的临时接口的能力也会很有用。它不必是一个命名接口 - 只是一个值约束。
    【解决方案2】:

    PHP 也是如此;你真的不需要接口。但它们的存在是为了满足架构需求。在 PHP 中,您可以为有用的函数指定类型提示。

    第二,接口就是契约。 来自这个接口的所有对象都具有这些功能,这是一个正式的合同。最好确保您的课程满足这些要求,而不是记住:“mm,这个课程有 isEnabled() 但另一个是 checkIfEnabled()”。接口可帮助您实现标准化。处理派生对象的其他人不必检查名称是isEnabled 还是checkIfEnabled(最好让解释器发现这些问题)。

    【讨论】:

      【解决方案3】:

      由于您可以在动态语言中对任何对象调用任何方法,我不确定接口将如何以任何真正有用的方式发挥作用。没有要强制执行的合同,因为一切都是在调用时确定的——一个对象甚至可以在其生命周期内改变它是否符合“合同”,因为在整个运行时添加和删除方法。如果对象不履行合同,则调用将失败,或者如果它不实现成员,则调用将失败 - 对于大多数实际目的而言,这两种情况都是相同的。

      【讨论】:

      • 关于这个话题有一个knol (yes knol)
      【解决方案4】:

      我们在下面的页面中看到了一个很好的实现,这是我们的(它的短版)

      var Interface = function (methods) {
          var self = this;
          self.methods = [];
      
          for (var i = 0, len = methods.length; i < len; i++) {
              self.methods.push(methods[i]);
          }
      
          this.implementedBy = function (object) {
      
              for (var j = 0, methodsLen = self.methods.length; j < methodsLen; j++) {
                  var method = self.methods[j];
                  if (!object[method] || typeof object[method] !== 'function') {
                      return false;
                  }
              }
              return true;
          }
      };
      
      //Call
      var IWorkflow = new Interface(['start', 'getSteps', 'end']);
      if (IWorkflow.implementedBy(currentWorkFlow)) {
          currentWorkFlow.start(model);
      }
      

      整个示例位于: http://www.javascriptbank.com/how-implement-interfaces-in-javascript.html

      【讨论】:

        【解决方案5】:

        bob.js 提供了接口的另一种替代方案:

        1.检查接口是否实现:

        var iFace = { say: function () { }, write: function () { } };  
        var obj1 = { say: function() { }, write: function () { }, read: function () { } }; 
        var obj2 = { say: function () { }, read: function () { } }; 
        console.log('1: ' + bob.obj.canExtractInterface(obj1, iFace)); 
        console.log('2: ' + bob.obj.canExtractInterface(obj2, iFace)); 
        // Output: 
        // 1: true 
        // 2: false 
        

        2。从对象中提取接口并仍然正确执行功能:

        var obj = {  
            msgCount: 0, 
            say: function (msg) { console.log(++this.msgCount + ': ' + msg); }, 
            sum: function (a, b) { console.log(a + b); } 
        }; 
        var iFace = { say: function () { } }; 
        obj = bob.obj.extractInterface(obj, iFace); 
        obj.say('Hello!'); 
        obj.say('How is your day?'); 
        obj.say('Good bye!'); 
        // Output: 
        // 1: Hello! 
        // 2: How is your day? 
        // 3: Good bye! 
        

        【讨论】:

          猜你喜欢
          • 2011-12-24
          • 1970-01-01
          • 1970-01-01
          • 2010-09-12
          • 2015-03-09
          • 2013-01-03
          • 1970-01-01
          • 1970-01-01
          • 2014-09-23
          相关资源
          最近更新 更多