23

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

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

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

4

5 回答 5

9

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

于 2009-09-14T04:20:40.820 回答
4

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

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

于 2009-09-14T04:18:52.543 回答
3

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

于 2009-09-14T04:17:22.437 回答
2

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

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

于 2012-09-18T08:17:51.667 回答
0

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! 
于 2013-04-04T19:25:16.470 回答