【问题标题】:Proper Objective-C Helper "Wannabe" Private methods?正确的 Objective-C 助手“Wannabe”私有方法?
【发布时间】:2011-08-03 15:46:36
【问题描述】:

虽然我讨厌在这个问题上把马打死(我已经阅读了关于这个的各种文章),但是我想在我创建我的“自己的约定”之前获得更多关于这个问题的意见,以便从现在开始使用在 Objective-C 中编码时开启。

我想弄清楚的约定最终是如何(使用生产级代码的最佳编码实践)在类中使用私有方法。来自 C# 的背景,当我编写类时,通常会有一段代码在多个公共方法中重复(例如错误检查或 WCF 服务连接设置)。我通常会创建这段代码的一个块并将其放在一个私有方法中,以便只有这些公共方法可以访问。这样,如果我需要进行更改,我只需要在一个地方进行,而不是在一个班级中 10 个不同的地方进行,但是永远不会让用户能够调用这个私有方法。例如:

public Class A
{
    public void method1()
    {
        doErrorChecking()
        // Do more stuff
    }
    public void method2()
    {
        doErrorChecking()
        // Do more stuff
    }     
    private doErrorChecking() { //Error Checking Code}
}

我知道在 Objective-C 中没有真正的方法可以真正将最后一个方法设为私有,但我真的想确保当我在 Objective-C 中为 iOS 开发创建所有未来的类时,我会遵循最好的方法实践可用,因此将来不需要在此问题上进行代码重构(希望如此)。我注意到人们在谈论类别,其他人只是不将方法放在@interface 文件中,而其他人则使用扩展方法。目前我只是将方法实现放在@implementation 文件中,而不是接口文件中。我还让“想要的”私有方法有一个非常独特的名称,这样子类化或覆盖方法就不是问题了。这是我应该遵循的路径吗?或者对于这些特定场景有没有更好的方法来做到这一点?

【问题讨论】:

    标签: c# objective-c private-members


    【解决方案1】:

    是的,将您的功能提取到另一种方法中是完全合理的。我认为最好的方法是使用类延续,您可以将私有方法声明放入其中。它可以在.m 文件中的@implementation 块之上,所以它是不在公共标头中。

    @interface MyClass ()
    - (void)_privateMethod:(id)arg;
    @end
    

    类延续和普通类别(例如@interface MyClass (PrivateMethods))之间的区别在于编译器将要求您在主@implementation 块中实现方法,而不是拥有一个单独的@implementation MyClass (PrivateMethods) 块。在实现您所描述的辅助方法时,这可以说是可取的。

    在命名方面,_ 开头的私有方法名称(和 ivar 名称,就此而言)是相对常见的,尽管不是每个人都这样做 - 显然是 Apple reserves this for themselves,所以你应该选择一个不同的前缀。该语言不强制执行任何操作。

    【讨论】:

    • 同时回答,但你的回答更完整。同意。
    • About prefixing methods with an underscore: “不要使用下划线字符作为私有方法的前缀。Apple 保留此约定。”
    • +1 感谢您考虑我的评论 :)
    • 因此,如果我按照您在 ClassA 的实现中所述创建此接口 MyClass () 块,我假设我还将在此文件中列出 Myclass 的实现。所以我会有 1 个接口部分(MyClass),然后是 2 个实现(MyClass,ClassA)。如果我需要从 ClassA 访问实例变量等,我将如何使用这个类?
    • 对不起,我换了你的班级名称。我的意思是ClassA 在我所说的任何地方MyClass。基本上ClassA.h 将包含@interface ClassA /*public methods declarations*/ @endClassA.m 将包含@interface ClassA () /*private method declarations*/ @end@implementation ClassA /*both private & public method implementations*/ @end
    【解决方案2】:

    我肯定会使用类扩展。在实现文件中,在您的 @implementation 上方添加类似这样的内容:

    @interface A ()
    - (void) doErrorChecking;
    @end
    

    然后根据需要使用代码中的方法。尽管由于 Objective-c 的动态特性,没有方法是真正私有的,但这会在您的接口文件中模糊该方法,同时在技术上仍将其包含在您自己的“私有”接口中。一般来说,保留您的 .h 文件中的方法和属性可以供公共使用,同时将私有使用的方法和属性限制为实现文件中的类扩展。

    【讨论】:

      【解决方案3】:

      如果您只需要一组绝对不能被子类覆盖的可​​重用代码,您可以只创建一个常规 C 函数而不是方法。如果函数在类@implementation 块的范围内声明,它仍然可以访问对象的所有私有变量。不过,您需要传入指向 self 的指针,因为函数未绑定到特定对象

      所以它看起来像这样:

      static BOOL isInValidState(MyClass *);
      
      @implementation MyClass
      
      static BOOL isInValidState(MyClass *self) {
          if (self->somePrivateIvar == nil) {
              return NO;
          }
      
          if ([self->someString isEqualToString:@"pigsAreFlying"]) {
              return NO;
          }
      
          return YES;
      }
      
      - (void)method1 {
          if (isInValidState(self) == NO) {
              return;
          }
          // Do whatever method 1 does
      }
      
      - (void)method2 {
          if (isInValidState(self) == NO) {
              return;
          }
          // Do whatever method 2 does
      }
      
      @end
      

      因为函数不是类的方法列表的一部分,所以这个错误检查方法永远不能被覆盖。由于我们声明了它static,它只能在这个文件的范围内访问,这意味着它实际上是私有的;它不能被任何其他类的对象调用。

      【讨论】:

        猜你喜欢
        • 2017-09-17
        • 1970-01-01
        • 2012-05-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多