【问题标题】:Compare Protocol in Swift vs Interface in Java比较 Swift 中的协议与 Java 中的接口
【发布时间】:2015-08-31 18:50:11
【问题描述】:

我正在阅读来自Apple developer page 的 iOS 教程。

在我看来protocolinterface 几乎具有相同的功能。

  • 两者有区别吗?

  • 项目中的不同用法?

更新

是的,我确实阅读了上面的链接,但我仍然不确定protocolinterface 之间的区别和用法。当我提出这样的问题时,我希望看到有关该主题的简单解释。有时可能很难从文档中获取所有内容。

【问题讨论】:

  • Swift 中的协议和 Java 中的接口是相同的概念。见here
  • 我认为像这样关于语言差异的问题对于理解语言特征非常有用。而且我认为它们不会导致不必要的自以为是的答案,也不会很容易在文档中找到答案。所以我认为对这个问题投反对票是不合理的。
  • 这里有几个关于 Java 接口的现实世界中的关键点 - stackoverflow.com/a/41143492/294884 - 这对于任何刚接触 Swift、尝试 Java 的人来说都是关键
  • 在另一个方向上,值得记住的是,Swift 的整个存在的理由是它用于“面向协议的编程”。你在 Swift 中无处不在地使用“协议扩展”来做所有事情。例如here 是一个关于 Swift 的微妙问题(即:“关于协议扩展”),它说明了一些问题。
  • 在 Swift 中,使用协议名称而不是接口,因为在 Objective C 中来自 C 的头文件(无用的重复项)被称为接口

标签: java swift


【解决方案1】:

协议本质上与 Java 接口非常相似,除了:

  • Swift 协议还可以指定必须实现的属性(即字段)
  • Swift 协议需要通过使用 mutating 关键字来处理值/引用(因为协议可以通过结构、枚举或类来实现)。
  • 您可以在任何时候使用“协议组合”组合协议。这取代了旧的 swift protocol<A, B> 协议组合方式。例如,将必须遵守协议NamedAged 的函数参数声明为:
    func wishHappyBirthday(to celebrator: Named & Aged) {}

这些对于 Java 开发人员来说是显而易见的差异(或者至少是我目前发现的差异)。还有更多信息here

【讨论】:

  • "协议关键字":这真的很酷!我认为这就是类型系统理论社区中所谓的交集类型。在 Java 中,对于具有多个边界的类型参数,您只能使用这种类型。 This paper 建议在 Java 中将它们作为第一类类型引入,并用语法来表示它们。
  • 不错的总结。一些更重要的特性:Swift 协议还可以指定相关的类型要求——例如集合类型具有关联的索引类型,或者可比较类型的比较方法需要相同类型的参数。在 Swift 2.0 中,协议扩展可以为满足协议要求的类型添加实际功能。
  • @rickster Java 8 也可以通过使用 default keyword 标记方法来向接口添加实现。请参阅Oracle Tutorial
  • 协议 关键字现在已被删除,取而代之的是和号。所以你可以写: let c: A & B
  • 在 Swift 中,使用协议名称而不是接口,因为在 Objective C 中来自 C 的头文件(无用的重复项)被称为接口
【解决方案2】:

补充@Thomas Schar 的回答。 Swift 协议的魔力来自扩展。

  • Swift 协议可以通过扩展 (Swift
    2)。 Java 8 接口可以有默认实现,但不能 “追溯”完成。
  • 在 Swift 中,您可以“追溯”添加协议要求(以及
    它的实现(如果需要)到任何类或结构。
  • Swift 协议不遵循通用(即 <..>)自定义模式, 但是一个类型别名方案(即关联类型)。一开始可能会令人困惑,但可以避免
    在某些情况下会出现“尖括号失明”。
  • Swift 有一个高级的类型模式匹配,允许非常 具体在哪里以及如何应用协议要求和扩展。来自 Java 时可能会令人困惑,但它具有强大的功能。
  • 可以为属性/参数(即庆祝者: 协议)

让我摸不着头脑的一件事是,并非所有协议都可以用作属性类型。例如,如果您有一个带有 typealias 的协议,则不能直接将其用作属性类型(仔细考虑它是有道理的,但是来自 Java 的我们确实希望拥有像 userDao: IDao 这样的属性)。

【讨论】:

  • Swift 协议也可以有可选成员,这与 Java 接口不同。
  • 在 Swift 中经常出现的一个小问题是,(可笑地)没有抽象函数,所以你只需“打印你忘了这个!” ...stackoverflow.com/a/24111430/294884
  • @Fattie。您可以在函数上使用“required”关键字来指定它需要子类实现。所以真的,更像是一个小小的无知而不是一个实际的观点。
  • @DirkBester - 干杯 - 等等,你说的是初始化器??
  • 再次@DirkBester 我可能有些困惑,但不能在协议中的函数之前使用required,您只需得到'required' may only be used on 'init' declarations ...
【解决方案3】:

只添加一件事,因为我一直在检查协议组合:

您可以在任何时候使用 protocol 关键字组合协议。

这不再是真的。 基于此:https://github.com/apple/swift/blob/master/test/type/protocol_composition.swift

这是正确的:

func foo ( var1 : A & B ){}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-30
    • 1970-01-01
    • 1970-01-01
    • 2011-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-17
    相关资源
    最近更新 更多