适当的Objective-C助手“Wannabe”私人方法?

时间:2011-08-03 15:46:36

标签: c# objective-c private-members

虽然我讨厌在这个问题上击败一匹马(我已经阅读了关于此的各种文章),但我想在创建我自己的“自己的约定”之前获得更多关于此问题的意见在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文件中,而不是接口文件。我也让“想要”的私有方法有一个非常独特的名称,以便子类或覆盖方法不是问题。这是我应该遵循的道路吗?或者对于这些特殊情况,有更好的方法吗?

3 个答案:

答案 0 :(得分:9)

是的,想要将您的功能提取到另一种方法中是完全合理的。在我看来,最好的方法是使用类继续,您可以将私有方法声明放入其中。它可以超过@implementation中的.m块。文件,所以它不在公共标题中。

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

类继续和普通类别(例如@interface MyClass (PrivateMethods))之间的区别在于编译器将要求您在主@implementation块中实现方法,而不是单独的{{ 1}}阻止。在实现你所描述的辅助方法时,这是可取的。

就命名而言,使用@implementation MyClass (PrivateMethods)启动私有方法名称(以及ivar名称)相对常见,但不是每个人都 - 显然是Apple {{3所以你应该选择一个不同的前缀。该语言不强制执行任何操作。

答案 1 :(得分:3)

我肯定会使用类扩展。在实施文件中,请在@implementation

上方添加以下内容
@interface A ()
- (void) doErrorChecking;
@end

然后根据需要在代码中使用该方法。虽然由于objective-c的动态特性,没有任何方法是真正私有的,但这会使您的接口文件中的方法变得模糊,同时在技术上将其包含在您自己的“私有”接口中。通常,保留.h文件以获取可供公众使用的方法和属性,同时将私有使用方法和属性限制为实现文件中的类扩展。

答案 2 :(得分:3)

如果你只需要一个绝对不能被子类覆盖的可​​重用代码集,你可以只使用常规的C函数而不是方法。如果函数在类@implementation块的范围内声明,它仍然可以访问该对象的所有私有ivars。但是,您需要传入指向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,所以它只能在这个文件的范围内访问,这意味着它实际上是私有的;它不能被任何其他类的对象调用。