动态语言中的接口有什么意义吗?

发布于 2024-07-04 12:47:14 字数 309 浏览 15 评论 0原文

在像 Java 这样的静态语言中,你需要接口,因为 否则类型系统不会让你做某些事情。 但在 PHP 和 Python 这样的动态语言中,你只需采用 鸭子打字的优点。

PHP 支持接口。 Ruby 和 Python 没有它们。 所以没有他们你显然可以幸福地生活。

我主要是用 PHP 做我的工作,但从来没有真正用过 利用定义接口的能力。 当我需要一个 一组类来实现某些公共接口,然后 我只是在文档中描述它。

所以你怎么看? 不使用你不是会更好吗 动态语言中的接口吗?

In static languages like Java you need interfaces because
otherwise the type system just won't let you do certain things.
But in dynamic languages like PHP and Python you just take
advantage of duck-typing.

PHP supports interfaces.
Ruby and Python don't have them.
So you can clearly live happily without them.

I've been mostly doing my work in PHP and have never really
made use of the ability to define interfaces. When I need a
set of classes to implement certain common interface, then
I just describe it in documentation.

So, what do you think? Aren't you better off without using
interfaces in dynamic languages at all?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(17

倒数 2024-07-11 12:47:15

Python 3000 will have Abstract Base Classes. Well worth a read.

最终幸福 2024-07-11 12:47:15

在像 PHP 这样的语言中,不存在的方法调用会导致致命错误并导致整个应用程序崩溃,那么接口就有意义了。

在像 Python 这样的语言中,您可以捕获并处理无效的方法调用,但事实并非如此。

In a language like PHP where a method call that doesn't exist results in a fatal error and takes the whole application down, then yes interfaces make sense.

In a language like Python where you can catch and handle invalid method calls, it doesn't.

我乃一代侩神 2024-07-11 12:47:15

停止尝试用动态语言编写 Java。

Stop trying to write Java in a dynamic language.

﹎☆浅夏丿初晴 2024-07-11 12:47:15

除了其他答案之外,我只想指出 Javascript 有一个 instanceof 关键字,如果给定实例位于给定对象原型链中的任何位置,该关键字将返回 true。

这意味着,如果您使用原型链中的“接口对象”作为“实现对象”(两者对于 JS 来说都是普通对象),那么您可以使用 instanceof 来确定它是否“实现”它。 这对执行方面没有帮助,但在多态性方面确实有帮助——这是接口的一种常见用途。

MDN instanceof 参考

In addition to the other answers I just want to point out that Javascript has an instanceof keyword that will return true if the given instance is anywhere in a given object's prototype chain.

This means that if you use your "interface object" in the prototype chain for your "implementation objects" (both are just plain objects to JS) then you can use instanceof to determine if it "implements" it. This does not help the enforcement aspect, but it does help in the polymorphism aspect - which is one common use for interfaces.

MDN instanceof Reference

椵侞 2024-07-11 12:47:15

Java“接口”的用途之一是允许在 Java 中使用强类型 mixins。 您可以混合适当的超类以及为支持该接口而实现的任何其他方法。

Python 具有多重继承,因此它并不真正需要接口设计来允许来自多个超类的方法。

然而,我喜欢强类型的一些好处——主要是,我喜欢早期错误检测。 我尝试使用“类似接口”的抽象超类定义。

class InterfaceLikeThing( object ):
    def __init__( self, arg ):
        self.attr= None
        self.otherAttr= arg
    def aMethod( self ):
        raise NotImplementedError
    def anotherMethod( self ):
        return NotImplemented

这在某种程度上使界面正式化。 它没有提供子类符合预期的绝对证据。 但是,如果子类无法实现所需的方法,我的单元测试将失败,并出现明显的 NotImplemented 返回值或 NotImplementedError 异常。

One use of the Java "interface" is to allow strongly-typed mixins in Java. You mix the proper superclass, plus any additional methods implemented to support the interface.

Python has multiple inheritance, so it doesn't really need the interface contrivance to allow methods from multiple superclasses.

I, however, like some of the benefits of strong typing -- primarily, I'm a fan of early error detection. I try to use an "interface-like" abstract superclass definition.

class InterfaceLikeThing( object ):
    def __init__( self, arg ):
        self.attr= None
        self.otherAttr= arg
    def aMethod( self ):
        raise NotImplementedError
    def anotherMethod( self ):
        return NotImplemented

This formalizes the interface -- in a way. It doesn't provide absolute evidence for a subclass matching the expectations. However, if a subclass fails to implement a required method, my unit tests will fail with an obvious NotImplemented return value or NotImplementedError exception.

情深缘浅 2024-07-11 12:47:15

首先,Ruby 确实没有 Interface,但他们有 mixin,它以某种方式吸收了其他语言的接口和抽象类的优点。

接口的主要目标是确保您的对象应实现接口本身中存在的所有方法。

当然,接口从来都不是强制性的,即使在 Java 中,当您不知道要操作的对象类型时,您也可以想象只使用类并使用反射来调用方法,但它很容易出错,应该不鼓励很多方法。

Well, first of all, it's right that Ruby does not have Interface as is, but they have mixin, wich takes somehow the best of both interfaces and abstract classes from other languages.

The main goal of interface is to ensure that your object SHALL implement ALL the methods present in the interface itself.

Of course, interface are never mandatory, even in Java you could imagine to work only with classes and using reflection to call methods when you don't know wich kind of object you're manipulating, but it is error prone and should be discouraged in many ways.

神爱温柔 2024-07-11 12:47:15

好吧,检查给定对象是否支持整个接口肯定会更容易,而不仅仅是在调用初始方法中使用的一两个方法时不崩溃,例如添加一个反对内部列表。

鸭子类型具有接口的一些好处,即到处都易于使用,但仍然缺少检测机制。

Well, it would certainly be easier to check if a given object supported an entire interface, instead of just not crashing when you call the one or two methods you use in the initial method, for instance to add an object to an internal list.

Duck typing has some of the benefits of interfaces, that is, easy of use everywhere, but the detection mechanism is still missing.

記柔刀 2024-07-11 12:47:15

这就像说您不需要动态类型语言中的显式类型。 为什么不把所有东西都变成“var”并在别处记录它们的类型呢?

这是程序员对程序员施加的限制。 这会让你更难搬起石头砸自己的脚; 让您犯错的空间更小。

It's like saying you don't need explicit types in a dynamically-typed language. Why don't you make everything a "var" and document their types elsewhere?

It's a restriction imposed on a programmer, by a programmer. It makes it harder for you to shoot yourself in the foot; gives you less room for error.

作死小能手 2024-07-11 12:47:15

作为一名 PHP 程序员,在我看来,接口基本上用作契约。 它让您说使用此接口的所有内容都必须实现一组给定的函数。

我不知道这是否有用,但当我试图理解接口的全部内容时,我发现它有点绊脚石。

as a PHP programmer, the way I see it, an Interface is basically used as a contract. It lets you say that everything which uses this interface MUST implement a given set of functions.

I dunno if that's all that useful, but I found it a bit of a stumbling block when trying to understand what Interfaces were all about.

流年已逝 2024-07-11 12:47:15

如果您觉得必须这样做,您可以实现一种带有函数的接口,该函数将对象的方法/属性与给定的签名进行比较。 这是一个非常基本的例子:

file_interface = ('read', 'readline', 'seek')

class InterfaceException(Exception): pass

def implements_interface(obj, interface):
    d = dir(obj)
    for item in interface:
        if item not in d: raise InterfaceException("%s not implemented." % item)
    return True

>>> import StringIO
>>> s = StringIO.StringIO()
>>> implements_interface(s, file_interface)
True
>>> 
>>> fp = open('/tmp/123456.temp', 'a')    
>>> implements_interface(fp, file_interface)
True
>>> fp.close()
>>> 
>>> d = {}
>>> implements_interface(d, file_interface)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in implements_interface
__main__.InterfaceException: read not implemented.

当然,这并不能保证太多。

If you felt you had to, you could implement a kind of interface with a function that compares an object's methods/attributes to a given signature. Here's a very basic example:

file_interface = ('read', 'readline', 'seek')

class InterfaceException(Exception): pass

def implements_interface(obj, interface):
    d = dir(obj)
    for item in interface:
        if item not in d: raise InterfaceException("%s not implemented." % item)
    return True

>>> import StringIO
>>> s = StringIO.StringIO()
>>> implements_interface(s, file_interface)
True
>>> 
>>> fp = open('/tmp/123456.temp', 'a')    
>>> implements_interface(fp, file_interface)
True
>>> fp.close()
>>> 
>>> d = {}
>>> implements_interface(d, file_interface)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in implements_interface
__main__.InterfaceException: read not implemented.

Of course, that doesn't guarantee very much.

你怎么敢 2024-07-11 12:47:14

我认为这更多的是一种便利。 如果您有一个函数接受“类似文件”的对象并且仅对其调用 read() 方法,那么强制用户实现某种 File 接口是不方便的 - 甚至是限制性的。 检查对象是否具有读取方法也同样容易。

但是,如果您的函数需要大量方法,则检查对象是否支持接口然后检查每个单独方法的支持会更容易。

I think of it more as a level of convenience. If you have a function which takes a "file-like" object and only calls a read() method on it, then it's inconvenient - even limiting - to force the user to implement some sort of File interface. It's just as easy to check if the object has a read method.

But if your function expects a large set of methods, it's easier to check if the object supports an interface then to check for support of each individual method.

你好,陌生人 2024-07-11 12:47:14

是的,有一点是,

如果您不显式使用接口,您的代码仍然使用该对象,就好像它实现了某些方法一样,只是不清楚未说出的接口是什么。

如果你定义一个函数来接受一个接口(比如 PHP),那么它会提前失败,并且问题将出现在调用者身上,而不是执行该工作的方法身上。 一般来说,早期失败是一个值得遵循的良好经验法则。

Yes, there is a point

If you don't explicitly use interfaces your code still uses the object as though it implemented certain methods it's just unclear what the unspoken interface is.

If you define a function to accept an interface (in PHP say) then it'll fail earlier, and the problem will be with the caller not with the method doing the work. Generally failing earlier is a good rule of thumb to follow.

别把无礼当个性 2024-07-11 12:47:14

接口实际上为拥有它们的静态语言(例如 Java)添加了某种程度的动态语言灵活性。 它们提供了一种查询对象在运行时为其实现合约的方法。

这个概念很好地移植到动态语言中。 当然,根据您对“动态”一词的定义,甚至包括 Objective-C,它在 Cocoa 中广泛使用了协议。

在 Ruby 中,您可以询问对象是否响应给定的方法名称。 但这是一个相当弱的保证,它会做你想做的事,特别是考虑到一遍又一遍地使用很少的单词,没有考虑完整的方法签名,等等。

在 Ruby 中,我可能会问

object.respond_to? :sync

所以,是的,它有一个名为“sync”的方法,无论它意味着什么。

在 Objective-C 中,我可能会问类似的问题,即“这看起来/行走/嘎嘎像同步的东西吗?”:

[myObject respondsToSelector:@selector(sync)]

更好的是,以一些冗长的代价,我可以问更具体的问题,即“这看起来/行走吗?” /quack 就像与 MobileMe 同步的东西?”:

[myObject respondsToSelector:@selector(sync:withMobileMeAccount:)]

这是鸭子打字到物种级别。

但是要真正询问一个对象是否有希望实现与 MobileMe 的同步...

[receiver conformsToProtocol:@protocol(MobileMeSynchronization)]

当然,您可以通过检查是否存在一系列选择器(您认为是协议/鸭子的定义)来实现协议,如果它们足够具体。 在这一点上,协议只是一大堆丑陋的responds_to的缩写? 查询,以及一些供编译器/IDE 使用的非常有用的语法糖。

接口/协议是对象元数据的另一个维度,可用于在处理这些对象时实现动态行为。 在 Java 中,编译器恰好要求正常方法调用执行此类操作。 但即使是 Ruby、Python、Perl 等动态语言也实现了超出“对象响应哪些方法”的类型概念。 因此就有了 class 关键字。 Javascript 是唯一一种没有这个概念的真正常用的语言。 如果您有类,那么接口也很有意义。

诚然,它对于更复杂的库或类层次结构比大多数应用程序代码更有用,但我认为这个概念在任何语言中都是有用的。

另外,其他人提到了mixin。 Ruby mixin 是一种共享代码的方式——例如,它们与类的实现相关。 接口/协议是关于类或对象的接口。 它们实际上可以互补。 您可能有一个指定行为的接口,以及一个或多个帮助对象实现该行为的mixins。

当然,我想不出任何语言真正具有这两种不同的一流语言特征。 在那些有 mixin 的情况下,包含 mixin 通常意味着它实现的接口。

Interfaces actually add some degree of dynamic lang-like flexibility to static languages that have them, like Java. They offer a way to query an object for which contracts it implements at runtime.

That concept ports well into dynamic languages. Depending on your definition of the word "dynamic", of course, that even includes Objective-C, which makes use of Protocols pretty extensively in Cocoa.

In Ruby you can ask whether an object responds to a given method name. But that's a pretty weak guarantee that it's going to do what you want, especially given how few words get used over and over, that the full method signature isn't taken into account, etc.

In Ruby I might ask

object.respond_to? :sync

So, yeah, it has a method named "sync", whatever that means.

In Objective-C I might ask something similar, i.e. "does this look/walk/quack like something that synchronizes?":

[myObject respondsToSelector:@selector(sync)]

Even better, at the cost of some verbosity, I can ask something more specific, i.e. "does this look/walk/quack like something that synchronizes to MobileMe?":

[myObject respondsToSelector:@selector(sync:withMobileMeAccount:)]

That's duck typing down to the species level.

But to really ask an object whether it is promising to implement synchronization to MobileMe...

[receiver conformsToProtocol:@protocol(MobileMeSynchronization)]

Of course, you could implement protocols by just checking for the presence of a series of selectors that you consider the definition of a protocol/duck, and if they are specific enough. At which point the protocol is just an abbreviation for a big hunk of ugly responds_to? queries, and some very useful syntactic sugar for the compiler/IDE to use.

Interfaces/protocols are another dimension of object metadata that can be used to implement dynamic behavior in the handling of those objects. In Java the compiler just happens to demand that sort of thing for normal method invocation. But even dynamic languages like Ruby, Python, Perl, etc. implement a notion of type that goes beyond just "what methods an object responds to". Hence the class keyword. Javascript is the only really commonly used language without that concept. If you've got classes, then interfaces make sense, too.

It's admittedly more useful for more complicated libraries or class hierarchies than in most application code, but I think the concept is useful in any language.

Also, somebody else mentioned mixins. Ruby mixins are a way to share code -- e.g., they relate to the implementation of a class. Interfaces/protocols are about the interface of a class or object. They can actually complement each other. You might have an interface which specifies a behavior, and one or more mixins which help an object to implement that behavior.

Of course, I can't think of any languages which really have both as distinct first-class language features. In those with mixins, including the mixin usually implies the interface it implements.

撑一把青伞 2024-07-11 12:47:14

我认为接口的使用更多地取决于有多少人将使用你的库。 如果只有您或一个小团队,那么文档和约定就可以了,而需要接口将是一个障碍。 如果它是一个公共库,那么接口会更有用,因为它们限制人们提供正确的方法而不仅仅是提示。 因此,界面对于编写公共库来说绝对是一个有价值的功能,我认为缺乏(或至少不强调)是动态语言更多地用于应用程序和强类型语言用于大型库的众多原因之一。

I think use of interfaces is determined more by how many people will be using your library. If it's just you, or a small team then documentation and convention will be fine and requiring interfaces will be an impediment. If it's a public library then interfaces are much more useful because they constrain people to provide the right methods rather than just hint. So interfaces are definitely a valuable feature for writing public libraries and I suppose that lack (or at least de-emphasis) is one of the many reasons why dynamic languages are used more for apps and strongly-typed languages are used for big libraries.

夏有森光若流苏 2024-07-11 12:47:14

我的印象是 Python 没有接口。 据我所知,在Python中你不能强制在编译时实现一个方法,因为它是一种动态语言。

Python 有一些接口库,但我没有使用过。

Python 也有 Mixins,因此您可以通过定义一个 Mixin 来创建一个 Interface 类,并为每个方法实现创建一个 pass ,但这并没有真正给您带来太多价值。

I was under the impression that Python doesn't have interfaces. As far as I'm aware in Python you can't enforce a method to be implemented at compilation time precisely because it is a dynamic language.

There are interface libraries for Python but I haven't used any of them.

Python also has Mixins so you could have create an Interface class by defining a Mixin an having pass for every method implementation but that's not really giving you much value.

櫻之舞 2024-07-11 12:47:14

Rene,请阅读我的回答到 StackOverflow 上的“用动态语言构建大型系统的最佳实践”问题。 我讨论了放弃动态语言的自由以节省开发工作并轻松地将新程序员引入项目的一些好处。 如果使用得当,接口将极大地有助于编写可靠的软件。

Rene, please read my answer to "Best Practices for Architecting Large Systems in a Dynamic Language" question here on StackOverflow. I discuss some benefits of giving away the freedom of dynamic languages to save development effort and to ease introducing new programmers to the project. Interfaces, when used properly, greatly contribute to writing reliable software.

或十年 2024-07-11 12:47:14

如果您没有高度的安全约束(因此没有人会以您不想的方式访问您的数据)并且您有良好的文档或训练有素的编码人员(因此他们不需要解释器/编译器来告诉他们要做什么做),那么不,没有用。

对于大多数中型项目,鸭子类型就足够了。

If you do not have hight security constraints (so nobody will access you data a way you don't want to) and you have a good documentation or well trained coders (so they don't need the interpreter / compiler to tell them what to do), then no, it's useless.

For most medium size projects, duck typing is all you need.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文