【问题标题】:Objective-C: when to use function vs methodObjective-C:何时使用函数与方法
【发布时间】:2013-05-27 22:43:45
【问题描述】:

我已经开始使用 Xcode 的重构功能(edit > refactor > extract)并注意到 Xcode 提供了提取方法函数.

我已阅读hereelsewhere 了解两者之间的区别,并了解方法 与类相关,而函数 则不相关。所以我不是在寻找定义,拜托。

假设不涉及任何参数,什么时候使用一个而不是另一个合适?我知道,如果某些东西与类无关,那么它可能是一个函数,但同样,这只是定义。我正在寻找好的用例。

就我个人而言,我正在尝试从 AppDelegate 的 applicationDidEnterBackground 中重构一些代码。由于它是进入后台时唯一处理事件的地方,因此清理代码的唯一方法是将子例程提取到......好吧,函数。但是它们会在 AppDelegate.m 中,所以它们不是方法吗?

嗯..

【问题讨论】:

  • 我在编写 sortedArrayUsingFunction 代码时使用了一个函数。

标签: objective-c


【解决方案1】:

就个人而言,我只在满足以下两个要求时才使用函数:

  1. 我在给定的课程中或整个项目中经常使用它,因此值得推广。
  2. 它没有副作用或上下文相关性(没有void *context 混乱)。

在我看来,C 风格的函数应该只作为最后的手段,或者在你真正需要在这种应用程序中进行函数式行为的情况下使用。事件处理既是特定于应用程序的,也是上下文敏感的,因此最好不要管它,专注于重构常见模式。

【讨论】:

  • 当您谈论离开事件处理时,您指的是 applicationDidEnterBackground 吗?
  • @arigold 我指的是任何方法。事件处理依赖于响应者链,这是一个非常“Objective-C”的概念,因此应该降级。
【解决方案2】:

函数的两个小而有意义的优点:

  • 可以将它们标记为static,仅用于内部,或者 __attribute__((visibility("hidden"))),对框架开发者很有帮助
  • 它们可以内联。例如,我使用这种模式来快速创建延迟队列:

    static inline dispatch_queue_t sharedQueue() { 
        static dispatch_queue_t queue; 
        static dispatch_once_t once; 
        dispatch_once(&once, ^{ 
            queue = dispatch_queue_create("foo", 0); 
        }); 
        return queue;
    }
    

【讨论】:

    【解决方案3】:

    当你有一个函数时,你会使用函数;-) 你知道定义:一个方法有一个隐式参数self,并且可以使用它访问实例变量;函数没有隐式参数——它需要的所有东西都必须传入。

    如果您要重构较大方法的部分,该部分不会访问实例变量,并且您不会重构它以便子类可以覆盖它,那么让 Xcode 为您构建一个函数。完成后将static 添加到它,使其对类是私有的。

    在这样做的过程中,你什么也没丢失,并且清楚地表明这段代码是一个函数——它不会改变对象的状态。

    在选择函数和方法之间当然没有硬性界限,它是一个模糊的边界。例如,如果一段代码只访问一个或两个实例变量但不更新它们,那么您可能会选择一个函数 - 再次明确表示对象状态没有被修改。但是您不想将大量实例变量作为参数传递,这很难阅读(而且效率低下)。

    使用函数可能很好,在 Objective-C 中这样做当然也不错。

    【讨论】:

      【解决方案4】:

      一个类的方法通常需要访问连接到该类的实例变量。 Objective-C 中的函数与类无关,因此无法访问类的任何非公共成员变量。

      考虑类 KNode,它包含成员变量 _memberVar。

      @interface KNode : NSObject {
          int _memberVar;
      }
      
      @end
      

      该类的任何方法都可以访问和更改成员变量,但任何旧函数都不能,因为它是私有的。

      @implementation KNode
      
      - (void)modify {
          _memberVar = 10;
      }
      
      @end
      

      以下功能不起作用

      void modify(KNode * node) {
          _memberVar = 10;
      }
      

      【讨论】:

        猜你喜欢
        • 2011-06-18
        • 2011-08-03
        • 2013-12-23
        • 1970-01-01
        • 1970-01-01
        • 2012-01-03
        • 1970-01-01
        • 2010-11-06
        • 1970-01-01
        相关资源
        最近更新 更多