当前位置:  开发笔记 > 编程语言 > 正文

在Objective-C中为类定义私有方法的最佳方法

如何解决《在Objective-C中为类定义私有方法的最佳方法》经验,为你挑选了5个好方法。

我刚刚开始编写Objective-C编程,并且具有Java背景,想知道编写Objective-C程序的人如何处理私有方法.

我理解可能存在一些惯例和习惯,并将此问题视为人们在Objective-C中使用私有方法的最佳技术的聚合器.

请在发布时为您的方法添加一个参数.它为什么好?它有哪些缺点(你知道)以及你如何处理它们?


至于到目前为止我的发现.

可以使用MyClass.m文件中定义的类别 [例如MyClass(Private)]来对私有方法进行分组.

这种方法有两个问题:

    Xcode(和编译器?)不检查您是否在相应的@implementation块中定义私有类别中的所有方法

    你必须把@interface声明你的私人类别在MyClass.m文件的开头,否则Xcode会抱怨"自己可能没有回复消息"privateFoo".

第一个问题可以解决空类 [例如MyClass()].
第二个困扰我很多.我希望在文件末尾附近实现(和定义)私有方法; 我不知道这是否可能.



1> Alex..:

正如其他人已经说过的那样,没有像Objective-C中的私有方法这样的东西.但是,从Objective-C 2.0(意味着Mac OS X Leopard,iPhone OS 2.0及更高版本)开始,您可以创建一个@interface MyClass ()名为Class Extension的空名称(即).类扩展的独特之处在于方法实现必须@implementation MyClass与公共方法相同.所以我像这样构建我的类:

在.h文件中:

@interface MyClass {
    // My Instance Variables
}

- (void)myPublicMethod;

@end

在.m文件中:

@interface MyClass()

- (void)myPrivateMethod;

@end

@implementation MyClass

- (void)myPublicMethod {
    // Implementation goes here
}

- (void)myPrivateMethod {
    // Implementation goes here
}

@end

我认为这种方法的最大优点是它允许您按功能对方法实现进行分组,而不是通过(有时是任意的)公共/私有区分.


使用LLVM 4编译器及其后,您甚至不需要这样做.您可以在实现中定义它们,而无需将它们放在类扩展中.
并且它将生成"MYClass可能不响应'-myPrivateMethod-",而不是异常/错误.
@Wienke不再需要担心订单.LLVM的最新版本将找到该方法,即使它出现在调用它的下方.
这实际上开始出现在Apple的样板代码中.++

2> 小智..:

Objective-C中没有真正的"私有方法",如果运行时可以解决使用它的实现将会做到这一点.但这并不是说没有方法不是文档化界面的一部分.对于那些方法,我认为一个类别是好的.而不是把@interface .m文件的顶部 2点,我将它放入自己的.h文件中.我遵循的惯例(并且已经在其他地方看到过,我认为这是一个Apple惯例,因为Xcode现在为它提供自动支持)就是在它的类和类别之后命名这样一个文件,用+分隔它们,所以@interface GLObject (PrivateMethods)可以找到它GLObject+PrivateMethods.h.提供头文件的原因是您可以在单元测试类中导入它:-).

顺便说一下,就.m文件末尾附近的实现/定义方法而言,可以通过实现.m文件底部的类别来实现类别:

@implementation GLObject(PrivateMethods)
- (void)secretFeature;
@end

或者使用类扩展(你称之为"空类"的东西),只需最后定义这些方法.Objective-C方法可以在实现中以任何顺序定义和使用,因此没有什么可以阻止您将"私有"方法放在文件的末尾.

即使有类扩展,我也会经常创建一个单独的标题(GLObject+Extension.h),以便在需要时可以使用这些方法,模仿"friend"或"protected"可见性.

由于这个答案是最初编写的,所以clang编译器已经开始为Objective-C方法进行两次传递.这意味着您可以完全避免声明"私有"方法,以及它们是否高于或低于调用站点,编译器将找到它们.



3> Andy..:

虽然我不是Objective-C专家,但我个人只是在我的类的实现中定义方法.当然,它必须在调用它的任何方法之前(上面)定义,但它绝对需要做最少量的工作.


方法排序不再重要.最新版本的LLVM不关心方法的实现顺序.所以你可以自己订购,而不需要先申报.
该解决方案的优点是避免添加多余的程序结构以避免编译器警告.
方法排序似乎是一个小问题,但如果将其转换为**代码可读性**,它可能会成为一个非常重要的问题,尤其是在团队中工作时.

4> justin..:

@implementation块中定义私有方法是大多数用途的理想选择.@implementation无论声明顺序如何,Clang都会在其中看到这些内容.无需在类继续(也称为类扩展)或命名类别中声明它们.

在某些情况下,您需要在类continuation中声明该方法(例如,如果在类continuation和之间使用选择器@implementation).

static 函数非常适用于特别敏感或速度至关重要的私有方法.

命名前缀的约定可以帮助您避免意外覆盖私有方法(我发现类名作为前缀安全).

@interface MONObject (PrivateStuff)由于加载时潜在的命名冲突,命名类别(例如)不是特别好的主意.它们真的只对朋友或受保护的方法有用(很少是一个很好的选择).为了确保您收到不完整类别实现的警告,您应该实际实现它:

@implementation MONObject (PrivateStuff)
...HERE...
@end

这是一个带注释的备忘单:

MONObject.h

@interface MONObject : NSObject

// public declaration required for clients' visibility/use.
@property (nonatomic, assign, readwrite) bool publicBool;

// public declaration required for clients' visibility/use.
- (void)publicMethod;

@end

MONObject.m

@interface MONObject ()
@property (nonatomic, assign, readwrite) bool privateBool;

// you can use a convention where the class name prefix is reserved
// for private methods this can reduce accidental overriding:
- (void)MONObject_privateMethod;

@end

// The potentially good thing about functions is that they are truly
// inaccessible; They may not be overridden, accidentally used,
// looked up via the objc runtime, and will often be eliminated from
// backtraces. Unlike methods, they can also be inlined. If unused
// (e.g. diagnostic omitted in release) or every use is inlined,
// they may be removed from the binary:
static void PrivateMethod(MONObject * pObject) {
    pObject.privateBool = true;
}

@implementation MONObject
{
    bool anIvar;
}

static void AnotherPrivateMethod(MONObject * pObject) {
    if (0 == pObject) {
        assert(0 && "invalid parameter");
        return;
    }

    // if declared in the @implementation scope, you *could* access the
    // private ivars directly (although you should rarely do this):
    pObject->anIvar = true;
}

- (void)publicMethod
{
    // declared below -- but clang can see its declaration in this
    // translation:
    [self privateMethod];
}

// no declaration required.
- (void)privateMethod
{
}

- (void)MONObject_privateMethod
{
}

@end

另一种可能不明显的方法是:C++类型既可以非常快速又可以提供更高程度的控制,同时最大限度地减少导出和加载的objc方法的数量.



5> dreamlax..:

您可以尝试在实现的下方或上方定义一个静态函数,该函数将指向您的实例.它将能够访问您的任何实例变量.

//.h file
@interface MyClass : Object
{
    int test;
}
- (void) someMethod: anArg;

@end


//.m file    
@implementation MyClass

static void somePrivateMethod (MyClass *myClass, id anArg)
{
    fprintf (stderr, "MyClass (%d) was passed %p", myClass->test, anArg);
}


- (void) someMethod: (id) anArg
{
    somePrivateMethod (self, anArg);
}

@end


我认为这是.m文件中真正的私有方法.其他类类别方法实际上不是私有的,因为你不能在@interface ... @ end block中为方法设置私有.
推荐阅读
手机用户2402852307
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有