【问题标题】:Does Swift support aspect oriented programming?Swift 是否支持面向方面的编程?
【发布时间】:2014-06-10 08:43:38
【问题描述】:

我是一名尝试学习面向方面编程的 iOS 开发人员,但 Swift 是否支持面向方面编程?

【问题讨论】:

    标签: ios swift


    【解决方案1】:

    Aspect Oriented Programming 的基础是拦截模式。我们从一个横切需求开始——需要在应用程序的许多部分中出现的东西。然后使用 切入点表达式,通过识别所有应应用此要求的位置来对其进行模块化。这是通过拦截方法调用并编织其他行为来完成的。因此,对于支持 AOP 的语言,它必须支持拦截模式。

    现在,根据语言的不同,可以在编译时、运行时或同时应用方法拦截。 Swift 在这方面是一个有趣的案例,因为它支持以下几种方法调度:

    • 静态/vtable,如 C++(更快:在测试中,方法调用时间约为 1.1 纳秒或更短)
    • Messaging,类似于 Objective-C(较慢:在测试中,方法调用时间大约为 4.9 纳秒)。也称为动态调度后期绑定

    如果您扩展 NSObject 或使用 @objc 装饰,则将使用消息传递。否则 Swift 将恢复为静态/vtable 方法调用。

    • 使用静态/vtable 类型的调度,只能在编译时拦截。对于 C++(和 Swift),这涉及在实际编译之前使用生成新源的预处理器。这是一种有些繁琐的方法,并且需要更多的精力来开发必要的工具。尽管它确实提供了最佳性能。
    • 还可以使用方法调用运行时拦截的消息传递样式。事实上,Objective-C 让拦截变得如此简单,以至于没有正式的 AOP 框架。它可能有用,但“原材料”太好了,没有人费心去制造。 Cooca 的许多最佳特性都利用了 Objective-C 的动态调度和拦截方法调用的能力。

    总结:

    • 如果您扩展 NSObject 或使用“@objc”装饰,Swift 将支持运行时 AOP。这有一些怪癖和限制——Apple 的关于在 Swift 中使用 KVO 的指南将指出其中的大部分。
    • 如果您不扩展 Objective-C 基础或使用“@objc”装饰,则只能使用编译时 AOP。目前还没有这样的库来提供编译时 AOP。此外,编译时 AOP 的一个缺点是它只适用于您拥有源代码的类。

    NB1: 一些语言,例如 Java,使用静态/vtable 风格的方法分派,并且仍然支持运行时方法拦截。这是可能的,因为它们依赖于虚拟机以及另一个连接点 类加载器。事实上,由于这个原因,Java 仍然被归类为“后期绑定”语言。

    NB2:它在技术上可以支持针对已编译到机器代码的二进制文件提供编译时编织,但有一些限制。首先是没有太多工具来支持这一点,因为实施工作量很大,并且必须在每个平台上重复。第二个是它限制了可用的 AOP 功能。

    【讨论】:

    • (有点旧)分析 vtable 与消息调度的来源:stackoverflow.com/a/907880/404201
    • 相关:Swift 类应该扩展 NSObject 吗? stackoverflow.com/q/24057525/404201
    • 嘿贾斯珀!虽然这是一个“旧”的答案,但谢谢。现在是 2018 年,您是否知道 Swift 4 中的 AOP 发生了什么变化?您知道我们可以利用哪些新功能来实现此功能?
    • 你好@Jimbo!我在 Swift5 中看到了关于编译时 AOP/装饰器的提议。除此之外什么都没有。
    【解决方案2】:

    不幸的是,Swift 本身目前还没有运行时支持。您必须依赖 Objective-C 桥接。

    这是一个全新的 iOS AOP 库,用 Objective-C 编写,支持 Swift。

    https://github.com/MO-AI/MOAspects

    只有 'before advice' 和 'after advice' 可用,但在大多数情况下,足以解决您的问题。 请注意,当对纯 Swift 类/方法的拦截无法正常工作时,可能需要向您的函数添加“动态”关键字。

    MOAspects 优于 Objective-C 的两个最著名的 AOP 库,Aspects 和 BlockInjection。 Aspects 不支持类方法拦截和多个挂钩到类层次结构中的方法。 BlockInjection 有一个关键问题是不支持 64 位。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-19
      • 1970-01-01
      • 2010-11-24
      • 2010-09-18
      • 2011-05-16
      • 2011-07-09
      • 2018-09-20
      • 1970-01-01
      相关资源
      最近更新 更多